#!/bin/bash
# ============================================================================
# NFShmXFrame CI/CD 构建脚本
# ============================================================================
#
# 本脚本用于 CI/CD 流水线中的自动化构建
#
# 功能：
#   1. 自动检测环境并安装依赖
#   2. 执行完整的构建流程（ccache 和 distcc 配置由 CMake 自动处理）
#   3. 生成构建报告
#
# 使用方法：
#   ./ci/build.sh [debug|release|dynamic-release|all]
#
# 参数：
#   -j, --jobs <N>                        - 并行任务数
#   -g, --game <NAME>                     - 游戏项目名称
#   -v, --verbose                         - 详细输出模式
#   -h, --help                            - 显示帮助信息
#
# 环境变量：
#   GAME_DIR           - 游戏项目名称（默认: LieRen）
#   JOBS               - 并行任务数（默认: nproc）
#   CLEAN_BUILD        - 清理后构建（默认: false）
#   SKIP_INSTALL_DEPS  - 跳过依赖安装（默认: 1，跳过安装；设为 0 强制安装）
#   CCACHE_DIR         - ccache 缓存目录（由 CMake 自动设置，默认: Build/<构建目录>/.ccache）
#   CCACHE_MAXSIZE     - ccache 最大缓存大小（默认: 50G）
#   USE_CLANG          - 使用 Clang 编译器（Linux 默认: 1，使用 Clang；设为 0 使用 GCC）
#   CLANG_VERSION      - Clang 版本（默认: 14，可选: 11, 12, 13, 14, 15, 16, 17, 18）
#   注意：ccache、distcc 和 Clang 配置已迁移到 CMake 系统，无需在 build.sh 中手动配置
#
# ============================================================================

set -e  # 遇到错误立即退出
# 注意: 不使用 set -u，因为需要检查可选的环境变量

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m' # No Color
BOLD='\033[1m'

# 监控进程 PID
MONITOR_PID=""
MONITOR_PID_FILE="/tmp/build_monitor_$$.pid"

# 记录构建开始时间
BUILD_START_TIME=$(date +%s)

# 清理函数（脚本退出时调用）
cleanup_monitor() {
    # 注意：动态负载均衡已由 CMake 处理，无需手动停止
    
    # 停止监控进程（静默，避免额外输出）
    if [ -n "$MONITOR_PID" ] && kill -0 "$MONITOR_PID" 2>/dev/null; then
        kill -9 "$MONITOR_PID" 2>/dev/null || true
        wait "$MONITOR_PID" 2>/dev/null || true
    fi

    # 从 PID 文件读取并清理
    if [ -f "$MONITOR_PID_FILE" ]; then
        local pid=$(cat "$MONITOR_PID_FILE" 2>/dev/null)
        if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
            kill -9 "$pid" 2>/dev/null || true
            wait "$pid" 2>/dev/null || true
        fi
        rm -f "$MONITOR_PID_FILE"
    fi

    # 清理临时文件（仅清理当前进程相关的文件）
    rm -f /tmp/build_monitor_$$.pid 2>/dev/null || true
    rm -f /tmp/icecc_env_gcc_$$.tar.gz 2>/dev/null || true

    # 清理环境变量（仅清理脚本内部使用的变量）
    unset DISTCC_HOSTS_FILE 2>/dev/null || true
    unset DISTCC_WRAPPER 2>/dev/null || true
    unset CCACHE_PREFIX_BACKUP 2>/dev/null || true
    
    # 恢复终端到正常状态
    tput cnorm 2>/dev/null || true
    tput sgr0 2>/dev/null || true

    # 移动光标到屏幕底部（避免打断时停在中间）
    tput cup $(tput lines) 0 2>/dev/null || true
    echo ""
}

# Ctrl+C 信号处理函数
handle_interrupt() {
    echo ""
    echo ""
    log_warning "⚠️ 构建已被中断 (Ctrl+C)"
    
    # 计算执行时间
    if [ -n "${BUILD_START_TIME:-}" ]; then
        local build_end_time=$(date +%s)
        local build_duration=$((build_end_time - BUILD_START_TIME))
        local minutes=$((build_duration / 60))
        local seconds=$((build_duration % 60))
        log_info "⏱️  执行时间: ${minutes} 分 ${seconds} 秒"
    fi
    
    # 显示日志文件位置
    if [ -n "${BUILD_LOG_FILE:-}" ] && [ -f "$BUILD_LOG_FILE" ]; then
        log_info "📋 构建日志已保存: ${BUILD_LOG_FILE}"
        log_info "    可以使用以下命令查看日志:"
        log_info "    cat ${BUILD_LOG_FILE}"
        log_info "    或查看错误: grep -i error ${BUILD_LOG_FILE}"
    fi
    
    # 清理监控进程
    cleanup_monitor
    
    # 退出（130 是 Ctrl+C 的标准退出码）
    exit 130
}

# 清理旧环境的函数（在脚本开始时调用）
cleanup_old_env() {
    # 清理旧的临时文件（不包括当前进程的文件）
    # 清理超过 1 天的旧文件
    find /tmp -maxdepth 1 -name 'build_monitor_*.pid' -mtime +1 -delete 2>/dev/null || true
    find /tmp -maxdepth 1 -name 'icecc_env_gcc_*.tar.gz' -mtime +1 -delete 2>/dev/null || true
    
    # 清理可能干扰的环境变量
    # 注意：不清理用户主动设置的变量，只清理脚本内部使用的变量
    unset DISTCC_HOSTS_FILE 2>/dev/null || true
    unset DISTCC_WRAPPER 2>/dev/null || true
    unset CCACHE_PREFIX_BACKUP 2>/dev/null || true
}

# 注册退出清理
trap cleanup_monitor EXIT
# 捕获 Ctrl+C 信号
trap handle_interrupt INT
# 捕获其他终止信号
trap cleanup_monitor TERM QUIT HUP

# 脚本开始时清理旧环境
cleanup_old_env

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

log_header() {
    echo ""
    echo -e "${BOLD}${CYAN}===================================================${NC}"
    echo -e "${BOLD}${CYAN}$1${NC}"
    echo -e "${BOLD}${CYAN}===================================================${NC}"
    echo ""
}

# ============================================================================
# 配置替换功能
# ============================================================================

# 获取本机IP地址（内网和外网）
get_local_ips() {
    local internal_ip=""
    local external_ip=""
    
    # 获取内网IP（排除127.0.0.1和docker网卡）
    if command -v ip &> /dev/null; then
        # Linux系统使用ip命令，排除回环地址和docker网卡
        internal_ip=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '^127\.' | grep -v '^172\.17\.' | grep -v '^172\.18\.' | grep -v '^169\.254\.' | head -n1)
    elif command -v ifconfig &> /dev/null; then
        # 使用ifconfig命令，排除回环地址和docker网卡
        internal_ip=$(ifconfig 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '^127\.' | grep -v '^172\.17\.' | grep -v '^172\.18\.' | grep -v '^169\.254\.' | head -n1)
    fi
    
    # 如果没有找到内网IP，尝试获取所有非回环IP
    if [ -z "$internal_ip" ]; then
        if command -v hostname &> /dev/null; then
            internal_ip=$(hostname -I 2>/dev/null | awk '{for(i=1;i<=NF;i++){if($i!~/^127\./ && $i!~/^172\.17\./ && $i!~/^172\.18\./ && $i!~/^169\.254\./){print $i;exit}}}')
        fi
    fi
    
    # 如果还是找不到，尝试使用route命令获取网关IP所在网段的IP
    if [ -z "$internal_ip" ]; then
        if command -v route &> /dev/null; then
            # 获取默认网关
            local gateway=$(route -n 2>/dev/null | grep '^0.0.0.0' | awk '{print $2}' | head -n1)
            if [ -n "$gateway" ]; then
                # 获取与网关同网段的IP
                if command -v ip &> /dev/null; then
                    internal_ip=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '^127\.' | head -n1)
                fi
            fi
        fi
    fi
    
    # 如果仍然找不到，返回空（不使用127.0.0.1）
    if [ -z "$internal_ip" ]; then
        internal_ip=""
    fi
    
    # 获取外网IP
    if command -v curl &> /dev/null; then
        external_ip=$(curl -s --max-time 3 ifconfig.me 2>/dev/null || curl -s --max-time 3 ifconfig.io 2>/dev/null || echo "")
        # 确保外网IP不是127.0.0.1
        if [ "$external_ip" = "127.0.0.1" ]; then
            external_ip=""
        fi
    fi
    
    # 如果无法获取外网IP，且内网IP不为空，使用内网IP
    if [ -z "$external_ip" ] && [ -n "$internal_ip" ]; then
        external_ip="$internal_ip"
    fi
    
    # 如果内网IP和外网IP都为空，返回空值（调用者需要处理）
    echo "$internal_ip|$external_ip"
}

# 解析文本配置文件并匹配IP
parse_config_file() {
    local config_file="$1"
    local internal_ip="$2"
    local external_ip="$3"
    
    if [ ! -f "$config_file" ]; then
        log_error "配置文件不存在: $config_file" >&2
        return 1
    fi
    
    # 读取配置文件，忽略注释行和空行，查找匹配的IP
    local matched_line=""
    local default_line=""  # 用于存储 127.0.0.1 的配置（作为默认配置）
    
    while IFS= read -r line || [ -n "$line" ]; do
        # 跳过注释行和空行
        line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
        if [[ -z "$line" ]] || [[ "$line" =~ ^# ]]; then
            continue
        fi
        
        # 提取第一个字段（IP地址）
        local config_ip=$(echo "$line" | cut -d'|' -f1)
        
        # 如果匹配内网IP或外网IP，则使用该配置
        if [ "$config_ip" = "$internal_ip" ] || [ "$config_ip" = "$external_ip" ]; then
            matched_line="$line"
            break
        fi
        
        # 同时记录 127.0.0.1 的配置作为默认配置
        if [ "$config_ip" = "127.0.0.1" ]; then
            default_line="$line"
        fi
    done < "$config_file"
    
    # 如果找到匹配的配置，直接返回（只输出配置行到stdout）
    if [ -n "$matched_line" ]; then
        echo "$matched_line" >&1
        return 0
    fi
    
    # 如果没找到匹配的配置，尝试使用 127.0.0.1 的配置作为默认
    if [ -n "$default_line" ]; then
        # 将警告信息输出到stderr，避免被捕获到stdout
        echo -e "${YELLOW}[WARNING]${NC} 未找到匹配的配置（内网IP: $internal_ip, 外网IP: $external_ip）" >&2
        echo -e "${BLUE}[INFO]${NC} 使用默认配置（127.0.0.1）" >&2
        # 只输出配置行到stdout
        echo "$default_line"
        return 0
    fi
    
    # 如果连默认配置都没有，返回错误
    echo -e "${YELLOW}[WARNING]${NC} 未找到匹配的配置（内网IP: $internal_ip, 外网IP: $external_ip）" >&2
    echo -e "${RED}[ERROR]${NC} 配置文件中也没有找到 127.0.0.1 的默认配置" >&2
    return 1
}

# 替换Common.lua中的变量
replace_lua_variable() {
    local lua_file="$1"
    local var_name="$2"
    local var_value="$3"
    
    if [ ! -f "$lua_file" ]; then
        log_error "Lua文件不存在: $lua_file"
        return 1
    fi
    
    # 处理字符串值（需要加引号）
    local is_string=false
    if [[ "$var_value" =~ ^[0-9]+$ ]]; then
        # 纯数字，不需要引号
        is_string=false
    else
        # 非纯数字，需要引号
        is_string=true
    fi
    
    # 转义特殊字符（用于perl/sed）
    # 注意：下划线 _ 不需要转义，但需要转义其他特殊字符
    local escaped_var_name=$(echo "$var_name" | sed 's/[[\.*^$()+?{|]/\\&/g')
    # 对于 Perl，值中的特殊字符需要转义，但替换时使用单引号避免 shell 解释
    local escaped_value=$(echo "$var_value" | sed 's/[[\.*^$()+?{|]/\\&/g')
    
    # 使用perl进行替换（更可靠，支持保留注释和分号）
    # 注意：等号前后可能有空格，如 NF_ST_WORLD_ID=1 或 NF_ST_WORLD_ID= 1 或 NF_ST_WORLD_ID = 1
    if command -v perl &> /dev/null; then
        # 创建临时文件用于检查是否发生替换
        local temp_file="${lua_file}.tmp.$$"
        # 使用 || true 防止 cp 失败导致脚本退出
        cp "$lua_file" "$temp_file" 2>/dev/null || true
        
        if [ ! -f "$temp_file" ]; then
            return 1
        fi
        
        # 在详细模式下，显示转义后的变量名和值
        if [ "${VERBOSE}" = "true" ]; then
            log_info "调试: 转义后的变量名 = '${escaped_var_name}'"
            log_info "调试: 转义后的值 = '${escaped_value}'"
            log_info "调试: 是否为字符串 = '$is_string'"
        fi
        
        # 简化替换逻辑：找到包含变量名的行，直接替换整行为 "变量名=值"（等号前后无空格）
        # 使用环境变量传递值，避免 shell 转义问题
        export PERL_VAR_NAME="${var_name}"
        export PERL_VAR_VALUE="${var_value}"
        export PERL_IS_STRING="${is_string}"

        # 直接修改临时文件
        local perl_output_file="${temp_file}.perl.$$"
        if [ "$is_string" = true ]; then
            # 字符串值：格式为 "变量名=\"值\""
            perl -pe '
                BEGIN {
                    $var_name = $ENV{PERL_VAR_NAME};
                    $var_value = $ENV{PERL_VAR_VALUE};
                }
                # 匹配包含变量名和等号的行（变量名后面必须有等号，避免部分匹配）
                # 支持格式：变量名=、变量名 =、变量名=值、变量名 = 值 等
                if (/^\s*\Q$var_name\E\s*[=]/) {
                    # 直接替换整行为标准格式（等号前后无空格）
                    $_ = "$var_name=\"$var_value\"\n";
                }
            ' "$temp_file" > "$perl_output_file" 2>/dev/null || cp "$temp_file" "$perl_output_file"
        else
            # 数字值：格式为 "变量名=值"
            perl -pe '
                BEGIN {
                    $var_name = $ENV{PERL_VAR_NAME};
                    $var_value = $ENV{PERL_VAR_VALUE};
                }
                # 匹配包含变量名和等号的行（变量名后面必须有等号，避免部分匹配）
                # 支持格式：变量名=、变量名 =、变量名=值、变量名 = 值 等
                if (/^\s*\Q$var_name\E\s*[=]/) {
                    # 直接替换整行为标准格式（等号前后无空格）
                    $_ = "$var_name=$var_value\n";
                }
            ' "$temp_file" > "$perl_output_file" 2>/dev/null || cp "$temp_file" "$perl_output_file"
        fi

        # 将处理后的文件移回临时文件
        if [ -f "$perl_output_file" ]; then
            mv "$perl_output_file" "$temp_file" 2>/dev/null || cp "$perl_output_file" "$temp_file"
            rm -f "$perl_output_file" 2>/dev/null || true
        fi

        # 清理环境变量
        unset PERL_VAR_NAME
        unset PERL_VAR_VALUE
        unset PERL_IS_STRING

        # 检查是否发生替换（比较文件内容）
        # 使用 || true 防止 diff 或 mv 失败导致脚本退出
        # 注意：即使 replace_success=1，也要检查文件是否真的被修改了
        # 使用 cmp 或 diff 比较文件，如果都不可用，使用 md5sum 或直接比较
        local files_differ=0
        if command -v cmp &> /dev/null; then
            if ! cmp -s "$lua_file" "$temp_file" 2>/dev/null; then
                files_differ=1
            fi
        elif command -v diff &> /dev/null; then
            if ! diff -q "$lua_file" "$temp_file" >/dev/null 2>&1; then
                files_differ=1
            fi
        else
            # 如果 cmp 和 diff 都不可用，使用简单的文件大小比较（不够准确，但总比没有好）
            local orig_size=$(stat -f%z "$lua_file" 2>/dev/null || stat -c%s "$lua_file" 2>/dev/null || echo "0")
            local temp_size=$(stat -f%z "$temp_file" 2>/dev/null || stat -c%s "$temp_file" 2>/dev/null || echo "0")
            if [ "$orig_size" != "$temp_size" ]; then
                files_differ=1
            fi
        fi

        # 在详细模式下，显示调试信息
        if [ "${VERBOSE}" = "true" ]; then
            if [ "$files_differ" = "0" ]; then
                log_info "调试: 文件未发生变化，变量 $var_name 可能未匹配"
            else
                log_info "调试: 文件已发生变化，变量 $var_name 替换成功"
            fi
        fi

        if [ "$files_differ" = "0" ]; then
            # 文件没有变化，删除临时文件
            rm -f "$temp_file" 2>/dev/null || true
            return 1
        else
            # 文件有变化，应用替换
            mv "$temp_file" "$lua_file" 2>/dev/null || true
            return 0
        fi
    else
        # 如果没有perl，使用sed（兼容性较差）
        local temp_file="${lua_file}.tmp.$$"
        cp "$lua_file" "$temp_file"

        if [ "$is_string" = true ]; then
            # 字符串值：替换为 "value"，保留行尾注释和分号
            # 匹配：变量名 = 值（可能带引号）; 或 变量名 = 值 --注释
            # 等号后可能有空格
            sed -i.tmp "s/^\([[:space:]]*${escaped_var_name}[[:space:]]*=[[:space:]]*\)[^;]*\([[:space:]]*[;]?[[:space:]]*.*\)$/\1\"${escaped_value}\"\2/" "$temp_file" 2>/dev/null || \
            sed -i.tmp "s/^\([[:space:]]*${escaped_var_name}[[:space:]]*=[[:space:]]*\).*$/\1\"${escaped_value}\"/" "$temp_file" 2>/dev/null
        else
            # 数字值：直接替换，保留行尾注释和分号
            # 等号后可能有空格，如 NF_ST_WORLD_ID= 1
            sed -i.tmp "s/^\([[:space:]]*${escaped_var_name}[[:space:]]*=[[:space:]]*\)[[:space:]]*[0-9]*\([[:space:]]*[;]?[[:space:]]*.*\)$/\1${escaped_value}\2/" "$temp_file" 2>/dev/null || \
            sed -i.tmp "s/^\([[:space:]]*${escaped_var_name}[[:space:]]*=[[:space:]]*\)[[:space:]]*[0-9]*$/\1${escaped_value}/" "$temp_file" 2>/dev/null || \
            sed -i.tmp "s/^\([[:space:]]*${escaped_var_name}[[:space:]]*=[[:space:]]*\).*$/\1${escaped_value}/" "$temp_file" 2>/dev/null
        fi

        # 如果替换成功，移动临时文件
        if [ -f "${temp_file}.tmp" ]; then
            mv "${temp_file}.tmp" "$lua_file"
        fi

        # 清理临时文件
        rm -f "${temp_file}" "${temp_file}.tmp" 2>/dev/null || true
    fi
}

# 替换 linux_servers.conf 中的变量（直接字符串替换）
replace_servers_conf_variable() {
    local conf_file="$1"
    local var_name="$2"
    local var_value="$3"

    if [ ! -f "$conf_file" ]; then
        log_error "配置文件不存在: $conf_file"
        return 1
    fi

    # 转义特殊字符（用于sed）
    local escaped_var_name=$(echo "$var_name" | sed 's/[[\.*^$()+?{|]/\\&/g')
    local escaped_value=$(echo "$var_value" | sed 's/[[\.*^$()+?{|]/\\&/g')

    # 使用 sed 进行全局替换（替换文件中所有出现的变量）
    if command -v sed &> /dev/null; then
        sed -i "s|${escaped_var_name}|${escaped_value}|g" "$conf_file" 2>/dev/null
        return $?
    else
        log_error "sed 命令不可用"
        return 1
    fi
}

# 主配置替换函数
replace_common_lua_config() {
    log_header "配置替换 - Common.lua 变量替换"

    # 获取脚本所在目录的绝对路径
    local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    local project_root="$(cd "$script_dir/.." && pwd)"

    # 默认配置
    local game_dir="${GAME_DIR:-LieRen}"
    # 使用目录结构：Conf/${game_dir}/server.conf
    local config_file="${CONFIG_FILE:-Conf/${game_dir}/server.conf}"
    local common_lua_file="Install/Plugin/${game_dir}/Common.lua"

    # 如果配置文件是相对路径，转换为绝对路径
    if [[ "$config_file" != /* ]]; then
        config_file="${project_root}/${config_file}"
    fi

    # 如果Common.lua是相对路径，转换为绝对路径
    if [[ "$common_lua_file" != /* ]]; then
        common_lua_file="${project_root}/${common_lua_file}"
    fi

    # 检查Common.lua文件是否存在
    if [ ! -f "$common_lua_file" ]; then
        log_error "Common.lua文件不存在: $common_lua_file"
        log_info "请检查游戏目录是否正确: $game_dir"
        return 1
    fi

    # 获取本机IP
    log_info "正在获取本机IP地址..."
    local ip_info=$(get_local_ips)
    local internal_ip=$(echo "$ip_info" | cut -d'|' -f1)
    local external_ip=$(echo "$ip_info" | cut -d'|' -f2)

    # 如果获取到的IP是127.0.0.1，说明没有找到真实IP，使用空值
    if [ "$internal_ip" = "127.0.0.1" ]; then
        internal_ip=""
    fi
    if [ "$external_ip" = "127.0.0.1" ]; then
        external_ip=""
    fi

    if [ -n "$internal_ip" ]; then
        log_info "内网IP: $internal_ip"
    else
        log_warning "无法获取内网IP（排除127.0.0.1）"
    fi

    if [ -n "$external_ip" ]; then
        log_info "外网IP: $external_ip"
    else
        log_warning "无法获取外网IP"
    fi

    # 解析配置文件
    log_info "正在解析配置文件: $config_file"
    # 使用临时文件分离stdout和stderr
    local temp_stdout=$(mktemp)
    local temp_stderr=$(mktemp)

    # 执行解析函数，分别捕获stdout和stderr
    parse_config_file "$config_file" "$internal_ip" "$external_ip" > "$temp_stdout" 2> "$temp_stderr"
    local parse_result=$?

    # 读取配置行（stdout）
    local config_line=$(cat "$temp_stdout")

    # 显示警告和错误信息（stderr）
    if [ -s "$temp_stderr" ]; then
        cat "$temp_stderr"
    fi

    # 清理临时文件
    rm -f "$temp_stdout" "$temp_stderr"

    if [ $parse_result -ne 0 ] || [ -z "$config_line" ]; then
        log_error "配置解析失败"
        return 1
    fi

    # 检查配置行是否包含警告信息（说明解析有问题）
    if echo "$config_line" | grep -qE "(WARNING|ERROR|未找到匹配|使用默认配置|\[INFO\]|\[WARNING\]|\[ERROR\])"; then
        log_error "配置解析失败：配置行包含警告信息"
        return 1
    fi

    log_success "找到匹配的配置"

    # 调试信息：显示匹配到的配置内容（如果启用详细模式）
    if [ "${VERBOSE}" = "true" ]; then
        log_info "匹配到的配置内容: $config_line"
    fi

    # 解析配置行：使用 $ 作为分隔符，分为两部分
    # 第一部分：用于 Common.lua 的配置（17个字段，用 | 分隔）
    # 第二部分：用于 linux_servers.conf 的配置（3个字段，用 | 分隔）
    local common_lua_config=""
    local servers_conf_config=""

    if echo "$config_line" | grep -q '\$'; then
        # 包含 $ 分隔符，分割为两部分
        common_lua_config=$(echo "$config_line" | cut -d'$' -f1)
        servers_conf_config=$(echo "$config_line" | cut -d'$' -f2)
    else
        # 不包含 $ 分隔符，只使用第一部分（向后兼容）
        common_lua_config="$config_line"
        servers_conf_config=""
    fi

    # 调试信息（如果启用详细模式）
    if [ "${VERBOSE}" = "true" ]; then
        log_info "Common.lua 配置部分: $common_lua_config"
        if [ -n "$servers_conf_config" ]; then
            log_info "linux_servers.conf 配置部分: $servers_conf_config"
        else
            log_info "linux_servers.conf 配置部分: (空)"
        fi
    fi

    # 需要替换的变量列表（按配置文件中字段的顺序）
    local vars=(
        "NF_ST_WORLD_ID"
        "NF_ST_ZONE_ID"
        "NF_ST_ZONE_ID2"
        "NF_ST_CROSS_ZONE_ID"
        "NF_INTER_SERVER_IP"
        "NF_INTER_CROSS_SERVER_IP"
        "NF_EXTER_SERVER_IP"
        "NF_EXTER_CROSS_SERVER_IP"
        "NF_EXTER_PROXY_SERVER_PORT"
        "NF_EXTER_PROXY_SERVER_UDP_PORT"
        "NF_MYSQL_IP"
        "NF_MYSQL_PORT"
        "NF_MYSQL_PASSWORD"
        "NF_REDIS_IP"
        "NF_REDIS_PORT"
        "NF_REDIS_PASS"
    )

    # 替换每个变量（使用第一部分配置）
    local replaced_count=0
    local skipped_count=0
    local field_index=2  # 从第2个字段开始（第1个是IP地址）

    for var in "${vars[@]}"; do
        # 从配置行中提取对应字段的值（跳过第一个IP字段）
        local var_value=$(echo "$common_lua_config" | cut -d'|' -f${field_index})

        # 去除首尾空格
        var_value=$(echo "$var_value" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')

        # 调试信息（如果启用详细模式）
        if [ "${VERBOSE}" = "true" ]; then
            log_info "调试: 变量 $var (字段 $field_index) 的值 = '$var_value'"
        fi

        if [ -n "$var_value" ] && [ "$var_value" != "" ]; then
            # 临时禁用 set -e，防止函数内部错误导致脚本退出
            set +e
            replace_lua_variable "$common_lua_file" "$var" "$var_value"
            local replace_result=$?
            set -e
            if [ $replace_result -eq 0 ]; then
                log_success "替换变量: $var = $var_value"
                replaced_count=$((replaced_count + 1))
            else
                log_warning "替换变量失败: $var"
                skipped_count=$((skipped_count + 1))
            fi
        else
            log_warning "配置中未找到变量: $var（字段 $field_index 为空），跳过"
            skipped_count=$((skipped_count + 1))
        fi
        
        field_index=$((field_index + 1))
    done
    
    # 显示结果
    log_info ""
    log_info "========================================"
    log_success "配置替换完成"
    log_info "  成功替换: $replaced_count 个变量"
    log_info "  跳过: $skipped_count 个变量"
    log_info "  目标文件: $common_lua_file"
    log_info "========================================"
    
    # 处理 linux_servers.conf 文件
    log_info ""
    log_header "配置替换 - linux_servers.conf 变量替换"
    
    # 源文件和目标文件路径
    local source_servers_conf="${project_root}/Conf/linux_servers.conf"
    local target_servers_conf="${project_root}/Install/linux_servers.conf"
    
    # 检查源文件是否存在
    if [ ! -f "$source_servers_conf" ]; then
        log_error "源文件不存在: $source_servers_conf"
        return 1
    fi
    
    # 确保 Install 目录存在
    local install_dir="${project_root}/Install"
    if [ ! -d "$install_dir" ]; then
        log_info "创建 Install 目录: $install_dir"
        mkdir -p "$install_dir"
    fi
    
    # 复制 linux_servers.conf 到 Install 目录
    log_info "复制文件: $source_servers_conf -> $target_servers_conf"
    cp "$source_servers_conf" "$target_servers_conf"
    if [ $? -ne 0 ]; then
        log_error "复制文件失败"
        return 1
    fi
    log_success "文件复制成功"
    
    # 从第一部分配置中读取 NF_ST_WORLD_ID 和 NF_ST_ZONE_ID（用于 linux_servers.conf）
    # 这些变量在 linux_servers.conf 的 ServerID 中使用（如 NF_ST_WORLD_ID.NF_ST_ZONE_ID.1.1）
    local nf_st_world_id=""
    local nf_st_zone_id=""
    
    # NF_ST_WORLD_ID 是第一部分配置的第2个字段（字段索引2，因为第1个是IP）
    nf_st_world_id=$(echo "$common_lua_config" | cut -d'|' -f2)
    # NF_ST_ZONE_ID 是第一部分配置的第3个字段（字段索引3）
    nf_st_zone_id=$(echo "$common_lua_config" | cut -d'|' -f3)
    
    # 去除首尾空格
    nf_st_world_id=$(echo "$nf_st_world_id" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
    nf_st_zone_id=$(echo "$nf_st_zone_id" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
    
    # 从第二部分配置中读取三个新字段（用 | 分隔）
    # 字段顺序：NF_ST_GAME_NAME(1) | NF_ST_GAME_DIR(2) | NF_ST_GAME_BIN(3)
    local nf_st_game_name=""
    local nf_st_game_dir=""
    local nf_st_game_bin=""
    
    if [ -n "$servers_conf_config" ] && [ "$servers_conf_config" != "" ]; then
        nf_st_game_name=$(echo "$servers_conf_config" | cut -d'|' -f1)
        nf_st_game_dir=$(echo "$servers_conf_config" | cut -d'|' -f2)
        nf_st_game_bin=$(echo "$servers_conf_config" | cut -d'|' -f3)
    fi
    
    # 去除首尾空格
    nf_st_game_name=$(echo "$nf_st_game_name" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
    nf_st_game_dir=$(echo "$nf_st_game_dir" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
    nf_st_game_bin=$(echo "$nf_st_game_bin" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
    
    # 调试信息（如果启用详细模式）
    if [ "${VERBOSE}" = "true" ]; then
        log_info "调试: NF_ST_WORLD_ID = '$nf_st_world_id'"
        log_info "调试: NF_ST_ZONE_ID = '$nf_st_zone_id'"
        log_info "调试: NF_ST_GAME_NAME = '$nf_st_game_name'"
        log_info "调试: NF_ST_GAME_DIR = '$nf_st_game_dir'"
        log_info "调试: NF_ST_GAME_BIN = '$nf_st_game_bin'"
    fi
    
    # 替换变量
    local servers_replaced_count=0
    local servers_skipped_count=0
    
    # 先替换第一部分配置中的变量（NF_ST_WORLD_ID 和 NF_ST_ZONE_ID）
    # 替换 NF_ST_WORLD_ID
    if [ -n "$nf_st_world_id" ] && [ "$nf_st_world_id" != "" ]; then
        replace_servers_conf_variable "$target_servers_conf" "NF_ST_WORLD_ID" "$nf_st_world_id"
        if [ $? -eq 0 ]; then
            log_success "替换变量: NF_ST_WORLD_ID = $nf_st_world_id"
            servers_replaced_count=$((servers_replaced_count + 1))
        else
            log_warning "替换变量失败: NF_ST_WORLD_ID"
            servers_skipped_count=$((servers_skipped_count + 1))
        fi
    else
        log_warning "配置中未找到变量: NF_ST_WORLD_ID（第一部分配置字段2为空），跳过"
        servers_skipped_count=$((servers_skipped_count + 1))
    fi
    
    # 替换 NF_ST_ZONE_ID
    if [ -n "$nf_st_zone_id" ] && [ "$nf_st_zone_id" != "" ]; then
        replace_servers_conf_variable "$target_servers_conf" "NF_ST_ZONE_ID" "$nf_st_zone_id"
        if [ $? -eq 0 ]; then
            log_success "替换变量: NF_ST_ZONE_ID = $nf_st_zone_id"
            servers_replaced_count=$((servers_replaced_count + 1))
        else
            log_warning "替换变量失败: NF_ST_ZONE_ID"
            servers_skipped_count=$((servers_skipped_count + 1))
        fi
    else
        log_warning "配置中未找到变量: NF_ST_ZONE_ID（第一部分配置字段3为空），跳过"
        servers_skipped_count=$((servers_skipped_count + 1))
    fi
    
    # 然后替换第二部分配置中的变量
    # 替换 NF_ST_GAME_NAME
    if [ -n "$nf_st_game_name" ] && [ "$nf_st_game_name" != "" ]; then
        replace_servers_conf_variable "$target_servers_conf" "NF_ST_GAME_NAME" "$nf_st_game_name"
        if [ $? -eq 0 ]; then
            log_success "替换变量: NF_ST_GAME_NAME = $nf_st_game_name"
            servers_replaced_count=$((servers_replaced_count + 1))
        else
            log_warning "替换变量失败: NF_ST_GAME_NAME"
            servers_skipped_count=$((servers_skipped_count + 1))
        fi
    else
        log_warning "配置中未找到变量: NF_ST_GAME_NAME（第二部分配置为空或字段1为空），跳过"
        servers_skipped_count=$((servers_skipped_count + 1))
    fi
    
    # 替换 NF_ST_GAME_DIR
    if [ -n "$nf_st_game_dir" ] && [ "$nf_st_game_dir" != "" ]; then
        replace_servers_conf_variable "$target_servers_conf" "NF_ST_GAME_DIR" "$nf_st_game_dir"
        if [ $? -eq 0 ]; then
            log_success "替换变量: NF_ST_GAME_DIR = $nf_st_game_dir"
            servers_replaced_count=$((servers_replaced_count + 1))
        else
            log_warning "替换变量失败: NF_ST_GAME_DIR"
            servers_skipped_count=$((servers_skipped_count + 1))
        fi
    else
        log_warning "配置中未找到变量: NF_ST_GAME_DIR（第二部分配置为空或字段2为空），跳过"
        servers_skipped_count=$((servers_skipped_count + 1))
    fi
    
    # 替换 NF_ST_GAME_BIN
    if [ -n "$nf_st_game_bin" ] && [ "$nf_st_game_bin" != "" ]; then
        replace_servers_conf_variable "$target_servers_conf" "NF_ST_GAME_BIN" "$nf_st_game_bin"
        if [ $? -eq 0 ]; then
            log_success "替换变量: NF_ST_GAME_BIN = $nf_st_game_bin"
            servers_replaced_count=$((servers_replaced_count + 1))
        else
            log_warning "替换变量失败: NF_ST_GAME_BIN"
            servers_skipped_count=$((servers_skipped_count + 1))
        fi
    else
        log_warning "配置中未找到变量: NF_ST_GAME_BIN（第二部分配置为空或字段3为空），跳过"
        servers_skipped_count=$((servers_skipped_count + 1))
    fi
    
    # 显示结果
    log_info ""
    log_info "========================================"
    log_success "linux_servers.conf 配置替换完成"
    log_info "  成功替换: $servers_replaced_count 个变量"
    log_info "  跳过: $servers_skipped_count 个变量"
    log_info "  目标文件: $target_servers_conf"
    log_info "========================================"
}

# 显示帮助信息
show_help() {
    cat << EOF
NFShmXFrame CI/CD 构建脚本

使用方法:
    $0 [选项] [构建类型]
    $0 init                  # 初始化环境（安装依赖）

代码生成目标:
    auto-make            - 执行代码生成（make auto-make）
    auto-make-all        - 清理后代码生成（make auto-make-all）
    auto-make-patch      - 补丁代码生成（make auto-make-patch）
    auto-make-patch-all  - 清理后补丁代码生成（make auto-make-patch-all）

构建类型（标准构建）:
    debug           - Debug 标准构建（make debug）
    release         - Release 标准构建（make release）
    dynamic-debug   - Dynamic Debug 标准构建（默认）⭐
    dynamic-release - Dynamic Release 标准构建（make dynamic-release）

构建类型（补丁构建 - GAME_VERSION_PATCH=1）:
    debug-patch           - Debug 补丁构建（make debug-patch）
    release-patch         - Release 补丁构建（make release-patch）
    dynamic-debug-patch   - Dynamic Debug 补丁构建（make dynamic-debug-patch）
    dynamic-release-patch - Dynamic Release 补丁构建（make dynamic-release-patch）

构建类型（清理后标准构建）:
    debug-all           - Debug 清理后标准构建（make debug-all）
    release-all         - Release 清理后标准构建（make release-all）
    dynamic-debug-all   - Dynamic Debug 清理后标准构建（make dynamic-debug-all）
    dynamic-release-all - Dynamic Release 清理后标准构建（make dynamic-release-all）

构建类型（清理后补丁构建）:
    debug-patch-all           - Debug 清理后补丁构建（make debug-patch-all）
    release-patch-all         - Release 清理后补丁构建（make release-patch-all）
    dynamic-debug-patch-all   - Dynamic Debug 清理后补丁构建（make dynamic-debug-patch-all）
    dynamic-release-patch-all - Dynamic Release 清理后补丁构建（make dynamic-release-patch-all）

特殊构建:
    all         - 全部版本标准构建
    all-clean   - 全部版本清理后构建

特殊命令:
    init            - 初始化环境，安装构建依赖 ⭐
    clean-all        - 清理所有构建目录的 CMake 缓存 🧹
    diagnose        - 诊断 distcc/ccache 环境 🔍
    auto-make       - 仅执行代码生成，不编译 ⭐
    cfg --game <DIR> - 根据配置文件替换 Common.lua 中的变量 ⚙️
                      (例如: cfg --game LieRen 或 --game LieRen cfg)

选项:
    -h, --help          - 显示帮助信息
    -j, --jobs N        - 并行任务数（默认: nproc）
    -g, --game DIR      - 游戏项目目录（默认: LieRen）
    -v, --verbose       - 详细输出
    --dry-run           - 仅打印命令，不执行 cmake 和 make/ninja
    --skip-makefiles    - 跳过代码生成步骤（proto/Excel 转换）

环境变量:
    GAME_DIR           - 游戏项目名称
    JOBS               - 并行任务数
    SKIP_INSTALL_DEPS  - 跳过依赖安装（1=跳过，0=安装，默认: 1）
    SKIP_MAKEFILES     - 跳过代码生成步骤（1=跳过，0=执行，默认: 0）
    CCACHE_DIR         - ccache 缓存目录（默认按构建类型独立）
    CCACHE_MAXSIZE     - ccache 最大缓存大小（每个构建类型独立）

工作流程:
    1. 首次使用（初始化环境）:
       $ ./ci/build.sh init                     # 安装依赖（需要 sudo 密码）

    2. 代码生成（proto/Excel 转换）:
       $ ./ci/build.sh auto-make                # 仅生成代码
       $ ./ci/build.sh auto-make-all            # 清理后生成代码
       $ ./ci/build.sh auto-make-patch          # 补丁模式生成

    3. 日常开发（标准构建）:
       $ ./ci/build.sh                          # Dynamic Debug 标准构建（默认）
       $ ./ci/build.sh debug                    # Debug 标准构建
       $ ./ci/build.sh release                  # Release 标准构建

    4. 补丁版本构建（GAME_VERSION_PATCH=1）:
       $ ./ci/build.sh debug-patch              # Debug 补丁构建
       $ ./ci/build.sh release-patch            # Release 补丁构建

    5. 问题排查（清理后构建）:
       $ ./ci/build.sh debug-all                # Debug 清理后标准构建
       $ ./ci/build.sh debug-patch-all          # Debug 清理后补丁构建

示例:
    $0 init                                     # 初始化环境（首次使用）⭐
    $0 auto-make                                # 仅生成代码 → make auto-make ⭐
    $0 auto-make-all                            # 清理后生成代码 → make auto-make-all
    $0 auto-make-patch                          # 补丁模式生成 → make auto-make-patch
    $0                                          # Dynamic Debug 标准构建（默认）
    $0 debug                                    # Debug 标准构建 → make debug
    $0 debug-patch                              # Debug 补丁构建 → make debug-patch ⭐
    $0 debug-all                                # Debug 清理后标准构建 → make debug-all
    $0 debug-patch-all                          # Debug 清理后补丁构建 → make debug-patch-all ⭐
    $0 -j 8 release                             # Release 标准构建（8 核心）
    $0 -j 8 release-patch                       # Release 补丁构建（8 核心）⭐
    $0 -j 8 release-patch-all                   # Release 清理后补丁构建（8 核心）
    $0 --game ShouYou dynamic-release           # ShouYou 项目 Dynamic Release 标准构建
    $0 --game ShouYou dynamic-release-patch     # ShouYou 项目 Dynamic Release 补丁构建 ⭐
    $0 --dry-run dynamic-debug                  # 仅打印 CMake 命令，不执行构建 🔍
    $0 --skip-makefiles dynamic-debug           # 跳过代码生成，直接编译 ⚡
    $0 all                                      # 全部版本标准构建
    $0 all-clean                                # 全部版本清理后构建
    $0 clean-all                                # 清理所有构建目录的 CMake 缓存 🧹

说明:
    - 标准构建: 调用 make xxx，执行 run-makefiles（不带 PATCH 参数）
    - 补丁构建（-patch 后缀）: 调用 make xxx-patch，执行 run-makefiles-patch（GAME_VERSION_PATCH=1）
      * 补丁构建会传递 GAME_VERSION_PATCH=1 给子 makefiles，用于版本补丁限制
      * patch 会比较生成代码与系统原有代码，不一样则返回失败
    - 清理后构建（-all 后缀）: 清理构建目录后重新构建
    - 组合后缀（-patch-all）: 清理后执行补丁构建

EOF
}

# 默认参数
GAME_DIR=${GAME_DIR:-LieRen}
BUILD_TYPE=""  # 构建类型，从命令行参数解析
JOBS=${JOBS:-$(nproc)}
CLEAN_BUILD=false  # 根据构建类型自动判断
SKIP_INSTALL_DEPS=${SKIP_INSTALL_DEPS:-1}  # 默认跳过依赖安装
INIT_MODE=false  # 初始化模式标志

# 编译器选择：Linux 上默认使用 Clang（更快），可通过环境变量覆盖
# 检测操作系统：在 Linux 上默认使用 Clang，Windows 上使用 GCC
if [ "$(uname -s)" = "Linux" ]; then
    USE_CLANG=${USE_CLANG:-1}  # Linux 默认使用 Clang
else
    USE_CLANG=${USE_CLANG:-0}  # 其他系统默认使用 GCC
fi
CLANG_VERSION=${CLANG_VERSION:-14}  # 默认 Clang 版本

# ============================================================================
# 诊断和修复函数
# ============================================================================

# 检测本机所有 IP 地址
check_local_ips() {
    local local_ips=""

    # 方法 1: hostname -I (内网 IP - Linux)
    if command -v hostname &> /dev/null; then
        local_ips=$(hostname -I 2>/dev/null || true)
    fi

    # 方法 2: ip addr (更可靠，支持多网卡)
    if command -v ip &> /dev/null; then
        local ip_ips=$(ip addr show 2>/dev/null | grep 'inet ' | awk '{print $2}' | cut -d/ -f1 | grep -v '127.0.0.1' || true)
        local_ips="${local_ips} ${ip_ips}"
    fi

    # 方法 3: ifconfig (兼容旧系统和 macOS)
    if command -v ifconfig &> /dev/null; then
        local ifconfig_ips=$(ifconfig 2>/dev/null | grep 'inet ' | awk '{print $2}' | grep -v '127.0.0.1' || true)
        local_ips="${local_ips} ${ifconfig_ips}"
    fi

    # 方法 4: 尝试获取公网 IP（快速检测，避免阻塞）
    if [ "${1:-}" = "--include-public" ]; then
        local public_ip=$(timeout 2 curl -s --max-time 2 ifconfig.me 2>/dev/null || \
                         timeout 2 wget -qO- --timeout=2 ifconfig.me 2>/dev/null || true)
        if [ -n "$public_ip" ]; then
            local_ips="${local_ips} ${public_ip}"
        fi
    fi

    # 去重和清理空值
    local_ips=$(echo "$local_ips" | tr ' ' '\n' | grep -v '^$' | sort -u | tr '\n' ' ')

    echo "$local_ips"
}


# 诊断 ccache 配置
diagnose_ccache() {
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    log_info "诊断 ccache 配置"
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""

    # 1. 检查 ccache 是否安装
    if command -v ccache &> /dev/null; then
        log_success "ccache: $(which ccache)"
        ccache --version | head -n1
        echo ""

        log_info "ccache 统计:"
        # 注意：ccache 配置已迁移到 CMake，缓存目录在构建目录下
        # 尝试从构建目录获取缓存路径，否则使用默认路径
        local ccache_dir=""
        if [ -f "Build/build64_debug/ccache_launcher.sh" ]; then
            ccache_dir=$(grep "CCACHE_DIR=" Build/build64_debug/ccache_launcher.sh | head -1 | cut -d'"' -f2)
        elif [ -f "Build/build64_release/ccache_launcher.sh" ]; then
            ccache_dir=$(grep "CCACHE_DIR=" Build/build64_release/ccache_launcher.sh | head -1 | cut -d'"' -f2)
        elif [ -f "Build/build64_dynamic_debug/ccache_launcher.sh" ]; then
            ccache_dir=$(grep "CCACHE_DIR=" Build/build64_dynamic_debug/ccache_launcher.sh | head -1 | cut -d'"' -f2)
        elif [ -f "Build/build64_dynamic_release/ccache_launcher.sh" ]; then
            ccache_dir=$(grep "CCACHE_DIR=" Build/build64_dynamic_release/ccache_launcher.sh | head -1 | cut -d'"' -f2)
        fi
        
        if [ -n "$ccache_dir" ] && [ -d "$ccache_dir" ]; then
            log_info "  缓存目录: $ccache_dir"
            CCACHE_DIR="$ccache_dir" ccache -s | head -15
        else
            ccache -s | head -15
        fi
        echo ""
    else
        log_error "ccache 未安装"
        echo ""
        return 1
    fi

    # 2. 检查 ccache 符号链接
    local ccache_dir="/usr/lib64/ccache"
    log_info "检查 ccache 编译器符号链接:"

    for compiler in gcc g++ cc c++; do
        local link_path="$ccache_dir/$compiler"
        if [ -L "$link_path" ]; then
            local target=$(readlink -f "$link_path")
            if [ -x "$target" ]; then
                log_success "$link_path -> $target ✓"
            else
                log_error "$link_path -> $target (目标不可执行)"
            fi
        elif [ -x "$link_path" ]; then
            log_success "$link_path 存在且可执行"
        else
            log_warning "$link_path 不存在或不可执行"
        fi
    done

    echo ""

    # 3. 检查环境变量
    log_info "ccache 环境变量:"
    log_info "  CCACHE_DIR: ${CCACHE_DIR:-未设置}"
    log_info "  CCACHE_PREFIX: ${CCACHE_PREFIX:-未设置}"
    log_info "  CCACHE_MAXSIZE: ${CCACHE_MAXSIZE:-未设置}"

    echo ""
}

# 诊断 distcc 配置
diagnose_distcc() {
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    log_info "诊断 distcc 配置"
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""

    # 1. 检查 distcc 是否安装
    if command -v distcc &> /dev/null; then
        log_success "distcc: $(which distcc)"
        distcc --version | head -n1
        echo ""
    else
        log_warning "distcc 未安装（可选）"
        echo ""
        return 0
    fi

    # 2. 检查配置文件
    log_info "检查 distcc 配置文件:"
    if [ -f "ci/distcc.conf" ]; then
        log_success "ci/distcc.conf 存在"

        # 加载配置
        source ci/distcc.conf 2>/dev/null || true

        log_info "  DISTCC_ENABLED: ${DISTCC_ENABLED:-未设置}"
        log_info "  DISTCC_HOSTS: ${DISTCC_HOSTS:-未设置}"
        log_info "  DISTCC_JOBS: ${DISTCC_JOBS:-未设置}"
    elif [ -f ".distcc.conf" ]; then
        log_success ".distcc.conf 存在"
        source .distcc.conf 2>/dev/null || true
        log_info "  DISTCC_ENABLED: ${DISTCC_ENABLED:-未设置}"
        log_info "  DISTCC_HOSTS: ${DISTCC_HOSTS:-未设置}"
        log_info "  DISTCC_JOBS: ${DISTCC_JOBS:-未设置}"
    else
        log_warning "distcc 配置文件不存在"
        log_info "  创建配置: cp ci/distcc.conf.example ci/distcc.conf"
    fi

    echo ""

    # 3. 检查递归调用风险 ⭐
    log_info "检查递归调用风险:"
    local has_recursion_risk=false

    # 检查本机是否运行 distccd 服务
    if systemctl is-active --quiet distccd 2>/dev/null || pgrep -x distccd &>/dev/null; then
        log_warning "  ❌ 本机正在运行 distccd 服务（可能导致递归）"
        log_info "     建议: sudo systemctl stop distccd"
        has_recursion_risk=true
    else
        log_success "  ✅ 本机未运行 distccd 服务"
    fi

    # 检查 CCACHE_PATH 是否设置（当使用 distcc 时）
    if [ "${CCACHE_PREFIX:-}" = "distcc" ]; then
        if [ -z "${CCACHE_PATH:-}" ]; then
            log_warning "  ❌ CCACHE_PATH 未设置（可能导致递归）"
            log_info "     建议: export CCACHE_PATH=\"/usr/bin:/usr/local/bin\""
            has_recursion_risk=true
        else
            log_success "  ✅ CCACHE_PATH 已设置: ${CCACHE_PATH}"
        fi
    fi

    if [ "$has_recursion_risk" = "false" ]; then
        log_success "  ✅ 无递归调用风险"
    fi

    echo ""

    # 4. 检查本机 IP
    log_info "检查本机 IP 地址:"
    local all_ips=$(check_local_ips --include-public)
    if [ -n "$all_ips" ]; then
        for ip in $all_ips; do
            log_success "  $ip"
        done
    else
        log_warning "  无法检测本机 IP"
    fi

    echo ""
}

# 测试编译器
test_compiler() {
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    log_info "测试编译器"
    log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""

    # 创建测试文件
    local test_file="/tmp/test_compile_$$.c"
    cat > "$test_file" << 'EOF'
#include <stdio.h>
int main() {
    printf("Hello, World!\n");
    return 0;
}
EOF

    local test_output="/tmp/test_compile_$$.o"

    # 测试 1: gcc
    log_info "测试 1: gcc"
    if gcc -c "$test_file" -o "$test_output" 2>&1; then
        log_success "gcc 编译成功"
        rm -f "$test_output"
    else
        log_error "gcc 编译失败"
    fi
    echo ""

    # 测试 2: ccache gcc
    log_info "测试 2: ccache gcc"
    if command -v ccache &> /dev/null; then
        if ccache gcc -c "$test_file" -o "$test_output" 2>&1; then
            log_success "ccache gcc 编译成功"
            rm -f "$test_output"
        else
            log_error "ccache gcc 编译失败"
        fi
    else
        log_warning "ccache 未安装，跳过"
    fi
    echo ""

    # 测试 3: /usr/lib64/ccache/gcc
    log_info "测试 3: /usr/lib64/ccache/gcc"
    if [ -x "/usr/lib64/ccache/gcc" ]; then
        if /usr/lib64/ccache/gcc -c "$test_file" -o "$test_output" 2>&1; then
            log_success "/usr/lib64/ccache/gcc 编译成功"
            rm -f "$test_output"
        else
            log_error "/usr/lib64/ccache/gcc 编译失败"
            /usr/lib64/ccache/gcc -c "$test_file" -o "$test_output" 2>&1 || true
        fi
    else
        log_warning "/usr/lib64/ccache/gcc 不存在，跳过"
    fi
    echo ""

    # 测试 4: distcc
    log_info "测试 4: distcc gcc"
    if command -v distcc &> /dev/null; then
        export DISTCC_HOSTS="localhost"
        export DISTCC_VERBOSE=0
        if distcc gcc -c "$test_file" -o "$test_output" 2>&1; then
            log_success "distcc gcc 编译成功"
            rm -f "$test_output"
        else
            log_error "distcc gcc 编译失败"
            export DISTCC_VERBOSE=1
            distcc gcc -c "$test_file" -o "$test_output" 2>&1 || true
        fi
    else
        log_warning "distcc 未安装，跳过"
    fi

    # 清理
    rm -f "$test_file" "$test_output"
    echo ""
}

# 完整诊断
run_full_diagnose() {
    echo ""
    log_info "═══════════════════════════════════════════════════════════════"
    log_info "开始完整诊断"
    log_info "═══════════════════════════════════════════════════════════════"
    echo ""

    # 1. 诊断 ccache
    diagnose_ccache

    # 2. 尝试修复 ccache
    # 注意：ccache 配置已迁移到 CMake，不再需要手动检查和修复符号链接
    if false; then
        log_warning "ccache 符号链接修复失败，可能需要手动修复"
    fi
    echo ""

    # 3. 诊断 distcc
    diagnose_distcc

    # 4. 测试编译器
    test_compiler

    # 5. 显示建议
    log_info "═══════════════════════════════════════════════════════════════"
    log_info "诊断完成"
    log_info "═══════════════════════════════════════════════════════════════"
    echo ""

    log_info "常见问题解决方案:"
    echo ""
    echo "  1. 如果 ccache 符号链接有问题:"
    echo "     sudo mkdir -p /usr/lib64/ccache"
    echo "     sudo ln -sf /usr/bin/ccache /usr/lib64/ccache/gcc"
    echo "     sudo ln -sf /usr/bin/ccache /usr/lib64/ccache/g++"
    echo ""
    echo "  2. 如果要启用 distcc:"
    echo "     cp ci/distcc.conf.example ci/distcc.conf"
    echo "     vim ci/distcc.conf  # 配置远程编译机"
    echo ""
    echo "  3. 如果 distcc 本机 IP 未过滤:"
    echo "     bash ci/check-local-ips.sh  # 查看本机 IP"
    echo "     vim ci/distcc.conf          # 使用内网 IP 而非公网 IP"
    echo ""
    echo "  4. 重新初始化环境:"
    echo "     ./ci/build.sh init"
    echo ""
}

# ============================================================================
# distcc 配置和自动检查
# ============================================================================

# 获取本地编译器主版本号（检测实际将被 CMake 使用的编译器）
# 根据 USE_CLANG 决定检查 Clang 还是 GCC
get_local_compiler_version() {
    local compiler_cmd=""
    local clang_version="${CLANG_VERSION:-14}"

    # 如果使用 Clang
    if [ "${USE_CLANG:-0}" = "1" ]; then
        # 优先级 1: 使用 CC 环境变量指定的编译器（但必须是 clang）
        if [ -n "$CC" ] && command -v "$CC" &> /dev/null; then
            # 验证 CC 指向的是 clang 而不是 gcc
            local cc_basename=$(basename "$CC" 2>/dev/null || echo "$CC")
            if [[ "$cc_basename" == clang* ]] || [[ "$CC" == *clang* ]]; then
                compiler_cmd="$CC"
            else
                # CC 指向的不是 clang，忽略它，使用下面的优先级
                compiler_cmd=""
            fi
        fi
        
        # 优先级 2: 使用版本化的 clang（如 clang-14）
        if [ -z "$compiler_cmd" ] && command -v "clang-${clang_version}" &> /dev/null; then
            compiler_cmd="clang-${clang_version}"
        fi
        
        # 优先级 3: 使用默认 clang
        if [ -z "$compiler_cmd" ] && command -v clang &> /dev/null; then
            compiler_cmd="clang"
        fi
        
        # 如果还是没找到，返回 unknown
        if [ -z "$compiler_cmd" ]; then
            echo "unknown"
            return 1
        fi
    else
        # 使用 GCC
        # 优先级 1: 使用 CC 环境变量指定的编译器
        if [ -n "$CC" ] && command -v "$CC" &> /dev/null; then
            compiler_cmd="$CC"
        # 优先级 2: 使用 /usr/bin/gcc（CMake 默认）
        elif [ -x "/usr/bin/gcc" ]; then
            compiler_cmd="/usr/bin/gcc"
        # 优先级 3: 使用 PATH 中的 gcc
        elif command -v gcc &> /dev/null; then
            compiler_cmd="gcc"
        else
            echo "unknown"
            return 1
        fi
    fi

    # 获取版本信息
    local version_output=$($compiler_cmd --version 2>/dev/null | head -n 1)
    
    # 验证编译器类型（确保检测到的是正确的编译器）
    if [ "${USE_CLANG:-0}" = "1" ]; then
        # 验证输出中是否包含 "clang"
        if ! echo "$version_output" | grep -qi "clang"; then
            # 输出中没有 "clang"，可能是检测到了错误的编译器
            echo "unknown"
            return 1
        fi
    else
        # 验证输出中是否包含 "gcc"
        if ! echo "$version_output" | grep -qi "gcc"; then
            # 输出中没有 "gcc"，可能是检测到了错误的编译器
            echo "unknown"
            return 1
        fi
    fi
    
    # 对于 Clang，版本格式通常是 "clang version 14.0.0" 或 "clang version 14.0.6"
    # 对于 GCC，版本格式通常是 "gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
    local version=""
    
    if [ "${USE_CLANG:-0}" = "1" ]; then
        # Clang 版本提取：匹配 "clang version X.Y.Z" 或 "clang version X.Y"
        # 方法1: 精确匹配 "clang version X.Y"
        version=$(echo "$version_output" | grep -oE 'clang version [0-9]+\.[0-9]+' | grep -oE '[0-9]+\.[0-9]+' | head -n 1 | cut -d. -f1)
        # 方法2: 如果没找到，尝试匹配 "clang version X.Y.Z"
        if [ -z "$version" ]; then
            version=$(echo "$version_output" | grep -oE 'clang version [0-9]+\.[0-9]+\.[0-9]+' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1 | cut -d. -f1)
        fi
        # 方法3: 如果还是没找到，尝试更宽松的匹配（但必须是第一个版本号）
        if [ -z "$version" ]; then
            version=$(echo "$version_output" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1 | cut -d. -f1)
        fi
    else
        # GCC 版本提取：匹配 "gcc (Ubuntu X.Y.Z) X.Y.Z" 或 "gcc version X.Y.Z"
        version=$(echo "$version_output" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1 | cut -d. -f1)
    fi
    
    echo "${version:-unknown}"
}


# 获取远程主机的完整信息（GCC 版本、CPU/内存负载、建议任务数等）
# 返回格式: key=value 形式的多行文本
get_remote_host_info() {
    local host_ip="$1"
    # 快速检查：1秒超时，不重试（版本检查是非关键操作）
    local timeout_sec=1
    local version_port=3633
    local verbose="${2:-false}"  # 调试模式

    # 🔥 第一步：使用 ping 判断网络是否联通
    # 如果 ping 不通，直接返回失败，不尝试获取 GCC 版本
    if command -v ping &> /dev/null; then
        local ping_result=1
        # Windows 和 Linux 的 ping 参数不同
        if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]] || [[ -n "${WINDIR:-}" ]]; then
            # Windows (Git Bash / Cygwin)
            ping -n 1 -w 1000 "$host_ip" &> /dev/null
            ping_result=$?
        else
            # Linux / Unix
            ping -c 1 -W 1 "$host_ip" &> /dev/null
            ping_result=$?
        fi
        
        if [ $ping_result -ne 0 ]; then
            # ping 不通，网络不联通，直接返回失败
            [ "$verbose" = "true" ] && echo "DEBUG: 主机 $host_ip PING 不通，跳过 GCC 版本检查" >&2
            return 1
        fi
    fi

    # 🔥 第二步：网络联通后，尝试获取 GCC 版本信息
    # 方法 1: 使用 nc (netcat) 获取完整信息
    if command -v nc &> /dev/null; then
        local raw_data=$(timeout ${timeout_sec} nc -w 1 "$host_ip" $version_port 2>/dev/null)
            if [ -n "$raw_data" ]; then
            [ "$verbose" = "true" ] && echo "DEBUG: nc data from $host_ip: $raw_data" >&2
                echo "$raw_data"
                return 0
            fi
    fi

    # 方法 2: 使用 bash /dev/tcp（内置，无需外部工具）
    if command -v timeout &> /dev/null; then
            local raw_data=$(timeout ${timeout_sec} bash -c "exec 3<>/dev/tcp/$host_ip/$version_port && cat <&3" 2>/dev/null)
            if [ -n "$raw_data" ]; then
            [ "$verbose" = "true" ] && echo "DEBUG: bash data from $host_ip: $raw_data" >&2
                echo "$raw_data"
                return 0
            fi
    fi

    return 1
}

# 获取远程主机的编译器主版本号
# 根据 USE_CLANG 决定获取 Clang 还是 GCC 版本
get_remote_compiler_version() {
    local host_ip="$1"
    local info=$(get_remote_host_info "$host_ip")
    if [ $? -eq 0 ]; then
        # 如果使用 Clang，优先获取 PRIMARY_COMPILER_MAJOR
        if [ "${USE_CLANG:-0}" = "1" ]; then
            local primary_compiler=$(echo "$info" | grep "^PRIMARY_COMPILER=" | cut -d= -f2 | tr -d '\r\n ')
            # 如果远程服务器主要使用 Clang，获取 Clang 版本
            if [ "$primary_compiler" = "clang" ]; then
                local version=$(echo "$info" | grep "^PRIMARY_COMPILER_MAJOR=" | cut -d= -f2 | tr -d '\r\n ')
                # 直接返回检测到的版本号（不进行合理性检查）
                if [ -n "$version" ] && [ "$version" != "unknown" ] && [ "$version" != "" ]; then
                    echo "$version"
                    return 0
                fi
            fi
            # 如果远程服务器没有 Clang 信息或版本未知，尝试获取 GCC 版本（作为备选）
            # 但这不是我们想要的，应该返回空值让调用者知道远程服务器没有 Clang
            # 不返回 GCC 版本，因为编译器类型不匹配
            echo ""
            return 1
        else
            # 使用 GCC，获取 GCC 版本
            local version=$(echo "$info" | grep "^GCC_MAJOR=" | cut -d= -f2 | tr -d '\r\n ')
            if [ -n "$version" ] && [ "$version" != "unknown" ]; then
                echo "$version"
                return 0
            fi
        fi
    fi
    echo ""
    return 1
}


# 检查远程 distcc 主机是否可用（端口连接 + 可选编译器版本检查）
# 返回值：
#   0 - 可用且版本匹配（或不检查版本）
#   1 - 端口不可访问/网络不通
#   2 - 无法获取远程编译器版本（版本服务未启动）
#   3 - 编译器版本不匹配
check_distcc_host() {
    local host_spec="$1"  # 格式: IP/cores,options 或 IP/cores 或 IP,options（错误格式）
    local check_compiler_version="${2:-false}"  # 是否检查编译器版本
    local local_compiler_version="${3:-}"  # 本地编译器版本
    local skip_port_check="${4:-false}"  # 是否跳过端口检查（用于已知可连接的主机）
    
    # 向后兼容：支持旧的参数名
    local check_gcc_version="${check_compiler_version}"
    local local_gcc_version="${local_compiler_version}"

    # 提取 IP 地址（需要处理多种格式）
    # 正确格式: 192.168.1.100/16,lzo
    # 错误格式: 192.168.1.100,lzo（缺少 /cores）
    local host_ip=$(echo "$host_spec" | sed 's|/.*||' | sed 's|,.*||')

    # 跳过 localhost（本地编译）
    if [ "$host_ip" = "localhost" ]; then
        return 0  # localhost 始终可用
    fi
    
    # 验证 IP 格式（避免空值或格式错误导致后续检查失败）
    if ! echo "$host_ip" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
        log_warning "主机规格 '$host_spec' IP 格式错误: '$host_ip'"
        return 1  # IP 格式错误
    fi

    # 第一步：检查端口 3632 是否可访问（除非明确跳过）
    if [ "$skip_port_check" = "false" ]; then
    local port=3632
    # 快速检查：2秒超时（提高可靠性，避免误判）
    local timeout_sec=2

    # 🔥 优先使用 ping 做预检查（Windows/Linux通用，最可靠）
    # 如果 ping 都不通，直接判定为不可达
    if command -v ping &> /dev/null; then
        local ping_result=1
        # Windows 和 Linux 的 ping 参数不同
        if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]] || [[ -n "${WINDIR:-}" ]]; then
            # Windows (Git Bash / Cygwin)
            ping -n 1 -w 1000 "$host_ip" &> /dev/null
            ping_result=$?
        else
            # Linux / Unix
            ping -c 1 -W 1 "$host_ip" &> /dev/null
            ping_result=$?
        fi
        
        if [ $ping_result -ne 0 ]; then
            # 🔥 ping 不通，记录日志并直接返回失败
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] ❌ 主机 $host_ip PING 不通（预检查失败）" >> /tmp/distcc_check_failed.log
            echo "  主机规格: $host_spec" >> /tmp/distcc_check_failed.log
            echo "  原因: 网络不可达或主机不存在" >> /tmp/distcc_check_failed.log
            echo "" >> /tmp/distcc_check_failed.log
            return 1  # 网络不通，直接返回
        fi
    fi

    # 🔥 第二步：检查端口连接（仅当 ping 通过后才执行）
    # 优先使用 nc -z（最可靠，专门用于端口检查）
    if command -v nc &> /dev/null; then
        # 使用 nc -z 检查端口是否真正开放（连接后立即关闭，不发送数据）
        local retry_count=1
        local nc_success=false
        
        for ((i=1; i<=$retry_count; i++)); do
            # nc -z: 只检查端口是否开放，不发送数据，连接成功后立即关闭
            # -w: 连接超时时间（秒）
            timeout ${timeout_sec} nc -z -w 2 "$host_ip" $port 2>/dev/null
            local nc_result=$?
            
            # nc -z 返回 0 表示端口开放，非 0 表示端口关闭或不可达
            if [ $nc_result -eq 0 ]; then
                nc_success=true
                break
            fi
            
            # 调试输出（只在第一次失败时）
            if [ $i -eq 1 ]; then
                echo "[$(date '+%Y-%m-%d %H:%M:%S')] 主机 $host_ip 端口 $port 连接失败（nc -z）" >> /tmp/distcc_check_failed.log
                echo "  主机规格: $host_spec" >> /tmp/distcc_check_failed.log
                echo "  返回码: $nc_result (0=端口开放, 1=端口关闭/不可达, 124=超时)" >> /tmp/distcc_check_failed.log
                echo "  说明: 端口可能未开放或 distcc 服务未运行" >> /tmp/distcc_check_failed.log
                echo "" >> /tmp/distcc_check_failed.log
            fi
            
            # 如果第一次失败，等待 1 秒后重试
            if [ $i -lt $retry_count ]; then
                sleep 1
            fi
        done
        
        if [ "$nc_success" = "false" ]; then
            return 1  # 端口不可访问
        else
            # 🔥 记录成功连接的主机（用于诊断）
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✅ 主机 $host_ip 端口 $port 连接成功（nc -z）" >> /tmp/distcc_check_success.log
            echo "  主机规格: $host_spec" >> /tmp/distcc_check_success.log
            echo "" >> /tmp/distcc_check_success.log
        fi
    elif command -v timeout &> /dev/null; then
        # 降级方案：使用 timeout + bash /dev/tcp 检查
        # 使用更可靠的方法：打开连接后立即关闭，检查返回码
        local retry_count=1
        local bash_success=false
        
        for ((i=1; i<=$retry_count; i++)); do
            # 打开 TCP 连接，立即关闭，检查是否成功
            # exec 3<>/dev/tcp/$host_ip/$port: 打开文件描述符 3 连接到 TCP 端口
            # exec 3<&-: 关闭输入
            # exec 3>&-: 关闭输出
            # 如果端口关闭，bash 会立即返回非 0 错误码
            # 将错误输出重定向到 /dev/null，只检查返回码
            timeout ${timeout_sec} bash -c "exec 3<>/dev/tcp/$host_ip/$port 2>/dev/null && exec 3<&- && exec 3>&-" 2>/dev/null
            local bash_result=$?
            local bash_output=""
            
            # 🔥 明确检查：只有返回码为 0 才算成功，其他所有情况（124=超时，其他=连接失败）都算失败
            if [ $bash_result -eq 0 ]; then
                bash_success=true
                break
            fi
            
            # 调试输出（只在第一次失败时）
            if [ $i -eq 1 ]; then
                echo "[$(date '+%Y-%m-%d %H:%M:%S')] 主机 $host_ip 端口 $port 连接失败（bash /dev/tcp）" >> /tmp/distcc_check_failed.log
                echo "  主机规格: $host_spec" >> /tmp/distcc_check_failed.log
                if [ $bash_result -eq 124 ]; then
                    echo "  返回码: $bash_result (超时)" >> /tmp/distcc_check_failed.log
                else
                    echo "  返回码: $bash_result (连接失败)" >> /tmp/distcc_check_failed.log
                fi
                echo "  说明: 端口可能未开放或 distcc 服务未运行" >> /tmp/distcc_check_failed.log
                echo "" >> /tmp/distcc_check_failed.log
            fi
            
            # 如果第一次失败，等待 1 秒后重试
            if [ $i -lt $retry_count ]; then
                sleep 1
            fi
        done
        
        if [ "$bash_success" = "false" ]; then
            return 1  # 端口不可访问
        else
            # 🔥 记录成功连接的主机（用于诊断）
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✅ 主机 $host_ip 端口 $port 连接成功（bash /dev/tcp）" >> /tmp/distcc_check_success.log
            echo "  主机规格: $host_spec" >> /tmp/distcc_check_success.log
            echo "" >> /tmp/distcc_check_success.log
        fi
    else
        # 没有 timeout 和 nc，尝试简单的 ping
        if ! ping -c 2 -W 2 "$host_ip" &> /dev/null; then
            return 1  # 网络不通
        fi
        # ping 通过，但无法验证端口，记录警告
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] ⚠️  主机 $host_ip 网络可达，但无法验证端口 $port（缺少 nc 和 timeout）" >> /tmp/distcc_check_failed.log
        echo "  主机规格: $host_spec" >> /tmp/distcc_check_failed.log
        echo "  建议: 安装 nc (netcat) 或 timeout 命令以进行准确的端口检查" >> /tmp/distcc_check_failed.log
        echo "" >> /tmp/distcc_check_failed.log
        # 无法验证端口，保守处理：返回失败
        return 1
    fi
    fi  # 结束 skip_port_check = false 的条件

    # 第二步：如果需要检查编译器版本
    if [ "$check_compiler_version" = "true" ] && [ -n "$local_compiler_version" ]; then
        local remote_version=$(get_remote_compiler_version "$host_ip")
        local compiler_name="GCC"
        if [ "${USE_CLANG:-0}" = "1" ]; then
            compiler_name="Clang"
        fi

        if [ -z "$remote_version" ]; then
            # 无法获取远程版本（版本服务未启动）
            return 2
        fi

        # 检查远程服务器是否使用正确的编译器类型
        if [ "${USE_CLANG:-0}" = "1" ]; then
            local remote_info=$(get_remote_host_info "$host_ip" "false")
            local remote_primary_compiler=$(echo "$remote_info" | grep "^PRIMARY_COMPILER=" | cut -d= -f2 | tr -d '\r\n ')
            
            # 如果远程服务器主要使用 GCC 而不是 Clang，应该警告
            if [ "$remote_primary_compiler" != "clang" ] && [ -n "$remote_primary_compiler" ]; then
                # 远程服务器使用 GCC，但本地使用 Clang，编译器类型不匹配
                DISTCC_HOST_VERSION_MISMATCH="${DISTCC_HOST_VERSION_MISMATCH:-} ${host_spec}(local:Clang-${local_compiler_version}/remote:GCC-${remote_version})"
                return 3
            fi
        fi

        if [ "$local_compiler_version" != "$remote_version" ]; then
            # 版本不匹配，保存信息到全局变量（显示编译器类型和版本）
            DISTCC_HOST_VERSION_MISMATCH="${DISTCC_HOST_VERSION_MISMATCH:-} ${host_spec}(local:${compiler_name}-${local_compiler_version}/remote:${compiler_name}-${remote_version})"
            return 3
        fi
    fi

    return 0  # 可用且版本匹配
}


# icecc 模式配置
setup_icecc() {
    log_info "配置 icecc 分布式编译..."
    
    # 检查 icecc 客户端是否已安装
    if ! command -v icecc &> /dev/null; then
        log_error "icecc 客户端未安装"
        log_info "请先运行: ./ci/build.sh init"
        log_info "或手动安装:"
        log_info "  Ubuntu/Debian: sudo apt-get install icecc"
        log_info "  CentOS/RHEL:   sudo yum install icecream"
        return 1
    fi
    
    # 设置 icecc 环境变量
    export ICECC_SCHEDULER_HOST="${ICECC_SCHEDULER_HOST:-}"
    export ICECC_NETNAME="${ICECC_NETNAME:-nfshm-build}"
    
    # 验证调度器地址
    if [ -z "$ICECC_SCHEDULER_HOST" ]; then
        log_error "未配置 ICECC_SCHEDULER_HOST"
        log_info "请在 ci/distcc.conf 中设置调度器地址"
        log_info "  示例: ICECC_SCHEDULER_HOST=172.18.63.1:8765"
        return 1
    fi
    
    # 创建编译器环境包（如果未指定）
    if [ -z "${ICECC_VERSION:-}" ]; then
        local env_file="/tmp/icecc_env_gcc_$$.tar.gz"
        
        # 检查是否已有缓存的环境包
        local cached_env="/tmp/icecc_env_gcc_cached.tar.gz"
        if [ -f "$cached_env" ]; then
            local age=$(($(date +%s) - $(stat -c%Y "$cached_env" 2>/dev/null || stat -f%m "$cached_env" 2>/dev/null || echo 0)))
            # 如果环境包不超过24小时，使用缓存
            if [ $age -lt 86400 ]; then
                log_info "使用缓存的编译器环境包（年龄: $((age/60)) 分钟）"
                env_file="$cached_env"
            else
                log_info "缓存的环境包已过期，重新创建..."
                rm -f "$cached_env"
            fi
        fi
        
        # 如果没有缓存或已过期，创建新的环境包
        if [ ! -f "$env_file" ]; then
            log_info "创建 icecc 编译器环境包..."
            
            # 查找 icecc-create-env 脚本
            local create_env_script=""
            if [ -x "/usr/libexec/icecc/icecc-create-env" ]; then
                create_env_script="/usr/libexec/icecc/icecc-create-env"
            elif [ -x "/usr/lib/icecc/bin/icecc-create-env" ]; then
                create_env_script="/usr/lib/icecc/bin/icecc-create-env"
            elif [ -x "/usr/lib/icecc/icecc-create-env" ]; then
                create_env_script="/usr/lib/icecc/icecc-create-env"
            elif command -v icecc-create-env &> /dev/null; then
                create_env_script="icecc-create-env"
            fi
            
            if [ -z "$create_env_script" ]; then
                log_warning "未找到 icecc-create-env 脚本"
                log_warning "icecc 将尝试自动创建环境包（可能较慢）"
            else
                # 创建环境包
                log_info "使用 $create_env_script 创建环境包..."
                if $create_env_script --gcc $(which gcc) $(which g++) > "$env_file" 2>/dev/null; then
                    log_success "✅ 编译器环境包创建成功: $env_file"
                    # 缓存环境包
                    cp "$env_file" "$cached_env" 2>/dev/null || true
                else
                    log_warning "环境包创建失败，icecc 将自动创建（首次编译可能较慢）"
                    rm -f "$env_file"
                    env_file=""
                fi
            fi
        fi
        
        # 设置 ICECC_VERSION（如果成功创建了环境包）
        if [ -n "$env_file" ] && [ -f "$env_file" ]; then
            export ICECC_VERSION="$env_file"
            log_info "   编译器环境: $env_file ($(du -h "$env_file" | cut -f1))"
        else
            log_info "   编译器环境: 自动创建（首次编译会稍慢）"
        fi
    else
        log_info "   编译器环境: ${ICECC_VERSION}"
    fi
    
    # 设置 CCACHE_PREFIX
    export CCACHE_PREFIX="icecc"
    
    # 设置编译器路径
    export CCACHE_PATH="/usr/bin:/usr/local/bin"
    export CC="/usr/bin/gcc"
    export CXX="/usr/bin/g++"
    
    log_info "✅ icecc 配置完成"
    log_info "   调度器地址: ${ICECC_SCHEDULER_HOST}"
    log_info "   网络名称: ${ICECC_NETNAME}"
    log_info "   CCACHE_PREFIX: ${CCACHE_PREFIX}"
    
    # 验证调度器连接（重要！）
    log_info "验证调度器连接..."
    local scheduler_ip=$(echo "$ICECC_SCHEDULER_HOST" | cut -d':' -f1)
    local scheduler_port=$(echo "$ICECC_SCHEDULER_HOST" | cut -d':' -f2)
    scheduler_port=${scheduler_port:-8765}
    
    # 测试网络连接
    local connection_ok=false
    if timeout 5 bash -c "cat < /dev/null > /dev/tcp/${scheduler_ip}/${scheduler_port}" 2>/dev/null; then
        log_success "✅ 网络可以连接到调度器 ${ICECC_SCHEDULER_HOST}"
        connection_ok=true
    else
        log_error "❌ 无法连接到调度器 ${ICECC_SCHEDULER_HOST}"
        echo ""
        log_error "错误诊断："
        log_error "  1. 调度器服务未运行或地址配置错误"
        log_error "  2. 网络不通或防火墙阻挡"
        log_error "  3. 端口 ${scheduler_port} 未开放"
        echo ""
        log_error "快速排查："
        echo ""
        echo "  # 在调度器节点（${scheduler_ip}）检查服务："
        echo "  sudo systemctl status icecc-scheduler"
        echo "  或"
        echo "  ./ci/icecc-status.sh scheduler"
        echo ""
        echo "  # 在当前机器测试网络："
        echo "  telnet ${scheduler_ip} ${scheduler_port}"
        echo "  或"
        echo "  nc -zv ${scheduler_ip} ${scheduler_port}"
        echo ""
        log_error "icecc 模式无法使用，切换回本地编译模式"
        echo ""
        
        # 切换回本地编译
        unset CCACHE_PREFIX
        unset ICECC_SCHEDULER_HOST
        unset ICECC_NETNAME
        unset ICECC_VERSION
        
        log_warning "已自动切换到本地编译模式"
        log_warning "修复调度器后，可重新运行编译"
        
        return 1
    fi
    
    # 等待调度器就绪（最多等待 10 秒）
    if [ "$connection_ok" = true ]; then
        log_info "等待调度器就绪..."
        local wait_count=0
        local max_wait=10
        
        while [ $wait_count -lt $max_wait ]; do
            # 通过日志检查调度器是否在运行
            # 这里我们简单等待几秒，确保调度器完全启动
            sleep 1
            ((wait_count++))
            
            # 再次测试连接
            if timeout 2 bash -c "cat < /dev/null > /dev/tcp/${scheduler_ip}/${scheduler_port}" 2>/dev/null; then
                log_success "✅ 调度器已就绪"
                break
            fi
        done
        
        if [ $wait_count -ge $max_wait ]; then
            log_warning "⚠️ 调度器响应缓慢，但将继续尝试连接"
        fi
    fi
    
    # 设置 JOBS（icecc 会自动管理并行度，这里使用一个合理的值）
    export JOBS="${DISTCC_JOBS:-$(nproc)}"
    export CMAKE_BUILD_PARALLEL_LEVEL="${JOBS}"
    
    log_info "   并行任务数: ${JOBS}"
    
    log_success "✅ icecc 分布式编译配置完成"
    log_info ""
    log_info "编译时如果仍然提示 'scheduler not yet found/selected'："
    log_info "  1. 检查调度器服务: ./ci/icecc-status.sh scheduler"
    log_info "  2. 检查网络连接: telnet ${scheduler_ip} ${scheduler_port}"
    log_info "  3. 查看调度器日志: journalctl -u icecc-scheduler -f"
    log_info ""
    
    return 0
}

# yadcc 模式配置
setup_yadcc() {
    log_info "配置 yadcc 分布式编译..."
    
    # 检查 yadcc 客户端是否已安装
    if ! command -v yadcc &> /dev/null; then
        log_error "yadcc 客户端未安装"
        log_info "请参考文档手动安装:"
        log_info "  https://github.com/Tencent/yadcc"
        return 1
    fi
    
    # 设置 yadcc 环境变量
    export YADCC_COORDINATOR_ADDR="${YADCC_COORDINATOR_ADDR:-}"
    export YADCC_ENABLE_CACHE="${YADCC_ENABLE_CACHE:-1}"
    
    # 验证调度器地址
    if [ -z "$YADCC_COORDINATOR_ADDR" ]; then
        log_error "未配置 YADCC_COORDINATOR_ADDR"
        log_info "请在 ci/distcc.conf 中设置调度器地址"
        log_info "  示例: YADCC_COORDINATOR_ADDR=172.18.63.1:7040"
        return 1
    fi
    
    # 设置 CCACHE_PREFIX
    export CCACHE_PREFIX="yadcc"
    
    # 设置编译器路径
    export CCACHE_PATH="/usr/bin:/usr/local/bin"
    export CC="/usr/bin/gcc"
    export CXX="/usr/bin/g++"
    
    log_info "✅ yadcc 配置完成"
    log_info "   调度器地址: ${YADCC_COORDINATOR_ADDR}"
    log_info "   远程缓存: $([ "$YADCC_ENABLE_CACHE" = "1" ] && echo "启用" || echo "禁用")"
    log_info "   CCACHE_PREFIX: ${CCACHE_PREFIX}"
    
    # 设置 JOBS
    export JOBS="${DISTCC_JOBS:-$(nproc)}"
    export CMAKE_BUILD_PARALLEL_LEVEL="${JOBS}"
    
    log_info "   并行任务数: ${JOBS}"
    
    return 0
}

# distcc 配置：加载分布式编译配置文件
# 注意：主机验证、JOBS 计算和动态均衡已迁移到 CMake 系统（cmake/DistccConfig.cmake）
# 此函数现在只用于 init 阶段的环境变量初始化
load_distcc_config() {
    # 优先使用项目根目录的配置文件（向后兼容）
    # 如果不存在，则使用 ci 目录下的配置文件
    local config_file=""
    if [ -f ".distcc.conf" ]; then
        config_file=".distcc.conf"
    elif [ -f "ci/distcc.conf" ]; then
        config_file="ci/distcc.conf"
    fi

    # 检查配置文件是否存在
    if [ -n "$config_file" ]; then
        log_info "加载分布式编译配置: $config_file (仅用于 init 阶段)"
        source "$config_file"
        
        # 获取编译模式
        local distcc_mode="${DISTCC_MODE:-distcc}"
        
        # 检查是否启用分布式编译
        if [ "${DISTCC_ENABLED:-no}" = "yes" ]; then
            # 根据模式选择不同的设置函数
            case "$distcc_mode" in
                icecc)
                    log_info "🎯 编译模式: icecc（智能调度）"
                    setup_icecc
                    return $?
                    ;;
                yadcc)
                    log_info "🎯 编译模式: yadcc（高性能缓存）"
                    setup_yadcc
                    return $?
                    ;;
                distcc|*)
                    log_info "🎯 编译模式: distcc（自定义负载均衡）"
                    # 继续执行下面的 distcc 配置逻辑
                    ;;
            esac
        else
            log_info "分布式编译已禁用（可在 ci/distcc.conf 中启用）"
            return 1
        fi
        
        # --- distcc 模式配置（已简化） ---
        # 注意：主机验证、JOBS 计算和动态均衡已迁移到 CMake 系统（cmake/DistccConfig.cmake）
        # 此函数现在只用于 init 阶段的基本配置加载
        if [ "${DISTCC_ENABLED:-no}" = "yes" ] && [ "$distcc_mode" = "distcc" ]; then
            log_info "distcc 配置已加载（主机验证和 JOBS 计算由 CMake 处理）"
            log_info "   配置文件: $config_file"
            log_info "   主机列表: ${DISTCC_HOSTS:-未设置}"
            log_info ""
            log_info "💡 提示: 实际编译时，CMake 会自动："
            log_info "   - 验证远程主机连接"
            log_info "   - 过滤本机 IP"
            log_info "   - 计算并设置 JOBS"
            log_info "   - 配置动态均衡（如果启用）"
            return 0
        else
            log_info "distcc 已禁用（可在 ci/distcc.conf 中启用）"
            return 1
        fi
    else
        # 配置文件不存在，提示用户
        if [ "${DISTCC_VERBOSE:-0}" = "1" ]; then
            log_info "distcc 配置文件不存在"
            log_info "如需启用分布式编译，请复制 ci/distcc.conf.example 为 ci/distcc.conf"
        fi
        return 1
    fi
}

# 注意：distcc 和 ccache 配置不在这里加载，而是在实际编译时按需加载
# 这样 auto-make 等不需要编译的命令就不会加载这些配置

CCACHE_MAXSIZE=${CCACHE_MAXSIZE:-50G}
VERBOSE=${VERBOSE:-false}
DRY_RUN=${DRY_RUN:-false}
SKIP_MAKEFILES=${SKIP_MAKEFILES:-0}

# 解析命令行参数
while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            show_help
            exit 0
            ;;
        -j|--jobs)
            JOBS="$2"
            shift 2
            ;;
        -g|--game)
            GAME_DIR="$2"
            shift 2
            ;;
        -v|--verbose)
            VERBOSE=true
            shift
            ;;
        --dry-run)
            DRY_RUN=true
            shift
            ;;
        --skip-makefiles)
            SKIP_MAKEFILES=1
            shift
            ;;
        init)
            INIT_MODE=true
            SKIP_INSTALL_DEPS=0
            shift
            ;;
        diagnose)
            # 运行完整诊断
            run_full_diagnose
            exit 0
            ;;
        cfg)
            # 配置替换命令，支持 --game 参数
            shift  # 移除 cfg 参数
            # 继续解析 cfg 命令的参数
            while [[ $# -gt 0 ]]; do
                case $1 in
                    -g|--game)
                        if [ -n "$2" ]; then
                            GAME_DIR="$2"
                            shift 2
                        else
                            log_error "--game 参数需要指定游戏目录"
                            exit 1
                        fi
                        ;;
                    *)
                        # 未知参数，可能是误输入
                        log_warning "未知参数: $1，将被忽略"
                        shift
                        ;;
                esac
            done
            # 检查是否指定了游戏目录
            if [ -z "$GAME_DIR" ]; then
                log_error "cfg 命令需要指定游戏目录，请使用: cfg --game LieRen"
                log_info "或者使用: --game LieRen cfg"
                exit 1
            fi
            replace_common_lua_config
            exit 0
            ;;
        auto-make|auto-make-all|auto-make-patch|auto-make-patch-all|\
        debug|debug-patch|debug-all|debug-patch-all|\
        release|release-patch|release-all|release-patch-all|\
        dynamic-debug|dynamic-debug-patch|dynamic-debug-all|dynamic-debug-patch-all|\
        dynamic-release|dynamic-release-patch|dynamic-release-all|dynamic-release-patch-all|\
        all|all-clean|clean-all)
            BUILD_TYPE="$1"
            # 根据构建类型自动判断是否需要清理构建
            case "${BUILD_TYPE}" in
                *-all|all-clean|clean-all)
                    CLEAN_BUILD=true
                    ;;
                *)
                    CLEAN_BUILD=false
                    ;;
            esac
            shift
            ;;
        *)
            log_error "未知参数: $1"
            show_help
            exit 1
            ;;
    esac
done

# 如果没有提供任何构建命令，显示帮助
if [ "$INIT_MODE" = false ] && [ -z "${BUILD_TYPE}" ]; then
    show_help
    exit 0
fi

# 开始构建
log_info "=========================================="
if [ "$INIT_MODE" = true ]; then
    log_info "NFShmXFrame 环境初始化"
else
    log_info "NFShmXFrame CI/CD 构建脚本"
fi
log_info "=========================================="
if [ "$INIT_MODE" = false ]; then
    log_info "项目: ${GAME_DIR}"
    log_info "构建类型: ${BUILD_TYPE}"
    if [ "${CLEAN_BUILD}" = "true" ]; then
        log_info "构建模式: 全量构建（清理后重新编译）"
    else
        log_info "构建模式: 增量构建（仅编译修改文件）⭐"
    fi
    log_info "并行任务数: ${JOBS}"
    log_info "跳过依赖安装: ${SKIP_INSTALL_DEPS}"
    if [ "${SKIP_MAKEFILES}" = "1" ]; then
        log_info "跳过代码生成: 是 (--skip-makefiles)"
    else
        log_info "跳过代码生成: 否"
    fi
    log_info "ccache 目录: ${CCACHE_DIR}"
    if [ "${DRY_RUN}" = "true" ]; then
        log_info "模式: 仅打印命令，不执行 (--dry-run)"
    fi
fi
log_info "=========================================="

# 记录开始时间
BUILD_START_TIME=$(date +%s)

# 检测操作系统
detect_os() {
    if [ -f /etc/os-release ]; then
        . /etc/os-release
        OS=$NAME
        VER=$VERSION_ID
    else
        OS=$(uname -s)
        VER=$(uname -r)
    fi
    log_info "操作系统: ${OS} ${VER}"
}

# 安装依赖（Ubuntu/Debian）
install_deps_ubuntu() {
    log_info "检查并安装基础构建工具（Ubuntu/Debian）..."

    # 检查是否需要 sudo
    SUDO=""
    if [ "$EUID" -ne 0 ]; then
        SUDO="sudo"
    fi

    # 更新软件源（完全自动化）
    log_info "更新软件源..."
    if DEBIAN_FRONTEND=noninteractive $SUDO apt-get update 2>&1 | grep -v "^debconf:" | grep -v "^Ign:" | grep -E "^(Get:|Hit:|Err:|E:)" || true; then
        log_success "✅ 软件源更新完成"
    else
        log_warning "⚠️  软件源更新失败（可能网络问题）"
        log_info "继续尝试安装..."
    fi
    echo ""

    # 安装基础构建工具（完全自动化，无用户交互）
    # 项目依赖的开发库请根据实际需要手动安装或在 Makefile 中配置
    log_info "正在安装构建工具（完全自动，无需确认）..."
    
    # 分批安装，避免某个包失败影响全部
    # 1. 安装核心工具（必须成功）
    log_info "安装核心工具 (build-essential, git)..."
    
    # 显示安装过程和错误信息（过滤无用的 debconf 消息）
    install_output=$(DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y \
        build-essential \
        git 2>&1 | grep -v "^debconf:" | grep -v "^dpkg-preconfigure:" | grep -v "^Selecting" | grep -v "^Preparing" | grep -v "^Unpacking")
    install_status=${PIPESTATUS[0]}
    
    if [ $install_status -eq 0 ]; then
        log_success "✅ 核心工具安装成功"
    else
        log_error "❌ 核心工具安装失败"
        log_info ""
        log_error "安装输出："
        echo "$install_output" | head -20
        log_info ""
        log_info "可能的原因："
        log_info "  1. 网络问题：无法连接软件源"
        log_info "  2. 软件源配置错误"
        log_info "  3. 磁盘空间不足"
        log_info "  4. 包依赖冲突"
        log_info ""
        log_info "建议操作："
        log_info "  1. 检查网络：ping archive.ubuntu.com"
        log_info "  2. 手动测试：sudo apt-get install -y build-essential"
        log_info "  3. 检查磁盘空间：df -h"
        log_info "  4. 查看软件源：cat /etc/apt/sources.list"
        log_info ""
        return 1
    fi
    
    # 2. 安装构建工具（可选，但会在验证时补装）
    log_info "安装构建工具 (cmake, ninja, ccache)..."
    DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y \
        cmake \
        ninja-build \
        ccache 2>&1 | grep -v "^debconf:" | grep -v "^dpkg-preconfigure:" | grep -v "^Selecting" | grep -v "^Preparing" | grep -v "^Unpacking" | grep -v "^Setting up" || \
        log_warning "⚠️  部分构建工具安装失败，稍后验证时补装..."
    
    # 3. 安装 Python 2.7（可选）
    DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y \
        python2.7 \
        python2.7-dev 2>&1 | grep -v "^debconf: " | grep -v "^dpkg-preconfigure:" &> /dev/null || \
        log_warning "Python 2.7 安装失败（将使用 Python 3）"
    
    # 4. 安装其他依赖（可选）
    DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq \
        libkrb5-dev 2>&1 | grep -v "^debconf: " | grep -v "^dpkg-preconfigure:" &> /dev/null || true
    
    log_success "✅ 基础工具安装完成"

    # 验证关键工具是否安装成功
    log_info "验证编译工具链..."
    local missing_tools=()
    
    if ! command -v gcc &> /dev/null; then
        missing_tools+=("gcc")
    fi
    
    if ! command -v g++ &> /dev/null; then
        missing_tools+=("g++")
    fi
    
    if ! command -v make &> /dev/null; then
        missing_tools+=("make")
    fi
    
    if [ ${#missing_tools[@]} -gt 0 ]; then
        log_error "❌ 关键编译工具未安装: ${missing_tools[*]}"
        log_info ""
        log_info "解决方案："
        log_info "  1. 手动安装："
        log_info "     sudo apt-get update"
        log_info "     sudo apt-get install -y build-essential"
        log_info ""
        log_info "  2. 检查系统源："
        log_info "     cat /etc/apt/sources.list"
        log_info ""
        log_info "  3. 如果是最小化安装的系统，可能需要启用完整仓库"
        return 1
    fi
    
    log_success "✅ 编译工具链验证通过"
    log_info "  - gcc: $(gcc --version 2>&1 | head -n1)"
    log_info "  - g++: $(g++ --version 2>&1 | head -n1)"
    log_info "  - make: $(make --version 2>&1 | head -n1)"
    
    # 验证 cmake（未安装则自动安装）
    if command -v cmake &> /dev/null; then
        log_success "✅ cmake 已安装: $(cmake --version 2>&1 | head -n1)"
    else
        log_warning "⚠️  cmake 未安装，尝试自动安装..."
        if DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq cmake 2>/dev/null; then
            log_success "✅ cmake 安装成功: $(cmake --version 2>&1 | head -n1)"
        else
            log_error "❌ cmake 安装失败"
            log_info "请手动安装: sudo apt-get install cmake"
            return 1
        fi
    fi
    
    # 验证 ninja（未安装则自动安装）
    if command -v ninja &> /dev/null; then
        log_success "✅ Ninja 构建工具已安装（更快、输出更清晰）"
    else
        log_warning "⚠️  Ninja 未安装，尝试自动安装..."
        if DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq ninja-build 2>/dev/null; then
            log_success "✅ Ninja 安装成功"
        else
            log_warning "⚠️  Ninja 安装失败（可选工具，不影响构建）"
            log_info "推荐手动安装: sudo apt-get install ninja-build"
        fi
    fi

    # 验证并安装 Clang 编译器（可选，用于提速编译）
    local clang_version="${CLANG_VERSION:-14}"
    if command -v clang &> /dev/null || command -v clang-${clang_version} &> /dev/null; then
        local clang_cmd=$(command -v clang-${clang_version} 2>/dev/null || command -v clang 2>/dev/null)
        log_success "✅ Clang 编译器已安装: $(${clang_cmd} --version 2>&1 | head -n1)"
    else
        log_info "检测到系统未安装 Clang 编译器（可选）"
        log_info "Clang 编译器通常比 GCC 编译速度快 10-20%"
        log_info "正在自动安装 Clang ${clang_version}..."
        
        # 尝试安装指定版本的 clang
        if DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq \
            clang-${clang_version} \
            lldb-${clang_version} \
            lld-${clang_version} 2>/dev/null; then
            log_success "✅ Clang ${clang_version} 安装成功"
            
            # 创建软链接（方便使用）
            if [ -f "/usr/bin/clang-${clang_version}" ] && ! [ -f "/usr/bin/clang" ]; then
                log_info "创建 clang 软链接..."
                $SUDO update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${clang_version} 100 2>/dev/null || true
                $SUDO update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${clang_version} 100 2>/dev/null || true
            fi
            
            log_info "  - Clang: $(clang-${clang_version} --version 2>&1 | head -n1)"
            log_info "  - Linux 上默认已启用 Clang，如需使用 GCC: export USE_CLANG=0"
        else
            log_warning "⚠️  Clang ${clang_version} 安装失败，尝试安装默认版本..."
            
            # 如果指定版本失败，尝试安装默认版本
            if DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq \
                clang \
                lldb \
                lld 2>/dev/null; then
                log_success "✅ Clang (默认版本) 安装成功"
                log_info "  - Clang: $(clang --version 2>&1 | head -n1)"
            else
                log_warning "⚠️  Clang 安装失败（可选工具，不影响构建，将使用 GCC）"
                log_info "推荐手动安装: sudo apt-get install clang-${clang_version}"
                log_info "或安装默认版本: sudo apt-get install clang"
            fi
        fi
    fi

    # 检查 Python 命令并创建软链接（智能版本选择）
    # 策略：通过实际测试判断 Python 3 是否能兼容运行 Python 2 代码
    #      - Python 3 能兼容 Python 2 代码：优先使用，并删除冗余的 Python 2.7
    #      - Python 3 不兼容 Python 2 代码：尝试安装能兼容的低版本 Python 3.9
    #      - 只有 Python 2.7：先尝试使用，失败后自动切换到 Python 3.9
    log_info "检查 Python 环境（智能版本选择）..."
    
    PYTHON_SELECTED=""
    PYTHON_VERSION_INFO=""
    PYTHON27_EXISTS=false
    PYTHON3_EXISTS=false
    PYTHON3_VERSION=""
    PYTHON3_MAJOR=0
    PYTHON3_MINOR=0
    
    # 检查 python2.7 是否存在
    if command -v python2.7 &> /dev/null; then
        PYTHON27_EXISTS=true
        log_info "✅ 检测到 python2.7: $(which python2.7)"
    fi
    
    # 检查 python3 是否存在并测试其对 Python 2 代码的兼容性
    PYTHON3_COMPATIBLE=false
    if command -v python3 &> /dev/null; then
        PYTHON3_EXISTS=true
        # 获取 python3 版本号（主版本.次版本）
        PYTHON3_VERSION=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')" 2>/dev/null || echo "0.0")
        PYTHON3_MAJOR=$(echo $PYTHON3_VERSION | cut -d. -f1)
        PYTHON3_MINOR=$(echo $PYTHON3_VERSION | cut -d. -f2)
        log_info "✅ 检测到 python3: $(which python3), 版本: $PYTHON3_VERSION"
        
        # 测试 Python 3 是否能兼容运行 Python 2 代码
        log_info "测试 Python 3 对 Python 2 代码的兼容性..."
        
        # 测试策略：检查 Python 版本特性和已知的兼容性问题
        # Python 3.10+ 移除了一些向后兼容的特性，导致许多 Python 2 代码无法直接运行
        if python3 -c "
import sys

# 兼容性判断标准：
# 1. Python 3.10+ 移除了许多 distutils 相关特性，影响 Python 2 项目构建
# 2. Python 3.10+ 修改了 collections 模块的导入方式
# 3. Python 3.10+ 对字符串格式化和类型检查更加严格

# 简单判断：Python 3.9 及以下版本认为兼容性较好
if sys.version_info.major == 3 and sys.version_info.minor <= 9:
    sys.exit(0)  # 兼容
else:
    sys.exit(1)  # 不兼容
" 2>/dev/null; then
            PYTHON3_COMPATIBLE=true
            log_success "✅ Python $PYTHON3_VERSION 能兼容运行 Python 2 风格代码"
        else
            PYTHON3_COMPATIBLE=false
            log_warning "⚠️  Python $PYTHON3_VERSION 无法兼容 Python 2 代码"
        fi
    fi
    
    # 场景1：存在能兼容 Python 2 代码的 Python 3
    if [ "$PYTHON3_EXISTS" = true ] && [ "$PYTHON3_COMPATIBLE" = true ]; then
        log_success "✅ Python $PYTHON3_VERSION 可作为 Python 2 的替代方案"
        PYTHON_SELECTED=$(which python3)
        PYTHON_VERSION_INFO="Python $PYTHON3_VERSION（兼容 Python 2 代码）"
        
        # 如果同时存在 python2.7，则删除 python2.7（因为已有兼容的 Python 3）
        if [ "$PYTHON27_EXISTS" = true ]; then
            log_info "检测到 Python 2.7 和兼容的 Python 3，删除冗余的 Python 2.7..."
            if DEBIAN_FRONTEND=noninteractive $SUDO apt-get remove -y -qq python2.7 python2.7-dev python2.7-minimal &> /dev/null; then
                log_success "✅ Python 2.7 已删除"
            else
                log_warning "⚠️  Python 2.7 删除失败（可能系统依赖）"
            fi
        fi
    
    # 场景2：不存在 Python 2.7 存在不兼容 Python 2 代码的 Python 3
    elif [ "$PYTHON27_EXISTS" = false ] && [ "$PYTHON3_EXISTS" = true ] && [ "$PYTHON3_COMPATIBLE" = false ]; then
        log_warning "⚠️  当前 Python $PYTHON3_VERSION 无法兼容 Python 2 代码"
        log_info "尝试安装能兼容 Python 2 代码的低版本 Python 3.9..."
        
        # 尝试安装 Python 3.9（完全自动化，无需用户交互）
        log_info "尝试自动安装 Python 3.9..."
        
        # 确保 software-properties-common 已安装（add-apt-repository 依赖）
        $SUDO apt-get install -y -qq software-properties-common &> /dev/null || true
        
        # 添加 PPA（-y 自动确认）
        if DEBIAN_FRONTEND=noninteractive $SUDO add-apt-repository -y ppa:deadsnakes/ppa &> /dev/null; then
            log_info "✅ PPA 添加成功，更新软件源..."
            $SUDO apt-get update -qq &> /dev/null || $SUDO apt update -qq &> /dev/null
            
            # 安装低版本 Python 3.9（能兼容 Python 2 代码）
            if DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python3.9 python3.9-dev python3.9-distutils &> /dev/null; then
                log_success "✅ 低版本 Python 3.9 安装成功（能兼容 Python 2 代码）"
                PYTHON_SELECTED="/usr/bin/python3.9"
                PYTHON_VERSION_INFO="Python 3.9（降级安装，能兼容 Python 2 代码）"
            else
                log_warning "⚠️  Python 3.9 安装失败，使用高版本系统 Python $PYTHON3_VERSION"
                PYTHON_SELECTED=$(which python3)
                PYTHON_VERSION_INFO="Python $PYTHON3_VERSION（高版本，不兼容 Python 2 代码）"
            fi
        else
            log_warning "⚠️  无法添加 PPA（可能网络问题），使用高版本系统 Python $PYTHON3_VERSION"
            PYTHON_SELECTED=$(which python3)
            PYTHON_VERSION_INFO="Python $PYTHON3_VERSION（高版本，不兼容 Python 2 代码）"
        fi
    
    # 场景3：只存在 Python 2.7（先尝试使用，失败后自动切换到能兼容 Python 2 的 Python 3.9）
    elif [ "$PYTHON27_EXISTS" = true ]; then
        log_info "检测到有 Python 2.7，尝试使用 Python 2.7 安装环境..."
        log_info "（如果 Python 2.7 环境配置失败，将自动切换到能兼容 Python 2 代码的 Python 3.9）"
        PYTHON_SELECTED=$(which python2.7)
        PYTHON_VERSION_INFO="Python 2.7（临时使用，失败后回退到能兼容 Python 2 代码的 Python 3.9）"
        
        # 标记需要稍后验证 Python 2.7 是否可用
        PYTHON27_FALLBACK=true
    
    # 场景4：都不存在（直接安装能兼容 Python 2 代码的 Python 3.9）
    else
        log_error "❌ 未找到 Python 2.7 或 Python 3"
        log_info "尝试安装能兼容 Python 2 代码的 Python 3.9..."
        
        # 确保 software-properties-common 已安装
        $SUDO apt-get install -y -qq software-properties-common &> /dev/null || true
        
        # 添加 PPA 并安装低版本 Python 3.9
        if DEBIAN_FRONTEND=noninteractive $SUDO add-apt-repository -y ppa:deadsnakes/ppa &> /dev/null; then
            $SUDO apt-get update -qq &> /dev/null || $SUDO apt update -qq &> /dev/null
            
            if DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python3.9 python3.9-dev python3.9-distutils &> /dev/null; then
                log_success "✅ 低版本 Python 3.9 安装成功（能兼容 Python 2 代码）"
                PYTHON_SELECTED="/usr/bin/python3.9"
                PYTHON_VERSION_INFO="Python 3.9（新安装，能兼容 Python 2 代码）"
            else
                log_error "❌ Python 3.9 安装失败"
                return 1
            fi
        else
            log_error "❌ 无法添加 PPA，无法安装 Python"
            log_info "请手动安装 Python："
            log_info "  sudo apt install -y python3 python3-dev python3-pip"
            return 1
        fi
    fi
    
    # 创建软链接到选定的 Python 版本
    if [ -n "$PYTHON_SELECTED" ]; then
        log_info "================================================"
        log_success "选定 Python: $PYTHON_VERSION_INFO"
        log_info "路径: $PYTHON_SELECTED"
        log_info "================================================"
        
        # 检查是否需要创建软链接
        if [ ! -e /usr/bin/python ] || [ "$(readlink -f /usr/bin/python 2>/dev/null)" != "$PYTHON_SELECTED" ]; then
            log_info "创建软链接: /usr/bin/python -> $PYTHON_SELECTED"
            if $SUDO ln -sf "$PYTHON_SELECTED" /usr/bin/python 2>/dev/null; then
                log_success "✅ 软链接创建成功"
                hash -r 2>/dev/null || true
            else
                log_warning "⚠️  无法创建软链接（权限不足）"
                log_info "请手动执行: sudo ln -sf $PYTHON_SELECTED /usr/bin/python"
            fi
        else
            log_info "✅ python 命令已正确指向: $PYTHON_SELECTED"
        fi
        
        # 显示最终的 Python 版本
        if command -v python &> /dev/null; then
            log_info "当前 python 版本: $(python --version 2>&1)"
        fi
    fi

    # 安装 setuptools（根据选定的 Python 版本）
    log_info "安装 Python setuptools（for $PYTHON_VERSION_INFO）..."
    
    SETUPTOOLS_INSTALL_SUCCESS=false
    
    # 根据选定的 Python 版本安装对应的 setuptools（完全自动化）
    if echo "$PYTHON_SELECTED" | grep -q "python2.7"; then
        # Python 2.7（自动安装，无需确认）
        if DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python-setuptools python2-dev 2>/dev/null; then
            SETUPTOOLS_INSTALL_SUCCESS=true
        else
            log_warning "Python 2.7 setuptools 安装失败（可能包不可用）"
        fi
        
        # 检查并安装 six 模块（Python 2.7 需要）
        log_info "检查 Python 2.7 six 模块..."
        if ! python2.7 -c "import six" 2>/dev/null; then
            log_warning "⚠️  six 模块未安装，正在安装..."
            # 尝试使用 pip 安装
            if python2.7 -m pip --version &>/dev/null; then
                if python2.7 -m pip install --user --quiet --no-warn-script-location --disable-pip-version-check six &>/dev/null; then
                    log_success "✅ six 模块安装成功（通过 pip）"
                else
                    log_warning "⚠️  通过 pip 安装 six 失败，尝试使用 apt-get..."
                    # 尝试使用 apt-get 安装
                    DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python-six 2>/dev/null || \
                    DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python2-six 2>/dev/null || \
                    log_warning "⚠️  six 模块安装失败（可能需要手动安装）"
                    
                    # 验证安装
                    if python2.7 -c "import six" 2>/dev/null; then
                        log_success "✅ six 模块安装成功（通过 apt-get）"
                    else
                        log_warning "⚠️  six 模块安装失败，某些功能可能不可用"
                        log_info "  手动安装命令: python2.7 -m pip install --user six"
                    fi
                fi
            else
                # pip 不可用，尝试使用 apt-get
                log_info "pip 不可用，尝试使用 apt-get 安装 six..."
                DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python-six 2>/dev/null || \
                DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python2-six 2>/dev/null || \
                log_warning "⚠️  six 模块安装失败（可能需要手动安装）"
                
                # 验证安装
                if python2.7 -c "import six" 2>/dev/null; then
                    log_success "✅ six 模块安装成功（通过 apt-get）"
                else
                    log_warning "⚠️  six 模块安装失败，某些功能可能不可用"
                    log_info "  手动安装命令: python2.7 -m pip install --user six"
                fi
            fi
        else
            SIX_VERSION=$(python2.7 -c "import six; print(six.__version__)" 2>/dev/null || echo "已安装")
            log_success "✅ six 模块已安装: $SIX_VERSION"
        fi
        
    elif echo "$PYTHON_SELECTED" | grep -q "python3.9"; then
        # Python 3.9（特定版本，自动安装）
        DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python3.9-distutils 2>/dev/null || true
        
        # 使用 pip 安装 setuptools（完全自动化）
        if ! $PYTHON_SELECTED -c "import setuptools" 2>/dev/null; then
            log_info "使用 pip 自动安装 setuptools for Python 3.9..."
            
            # 下载 get-pip.py（自动化，无用户交互）
            if command -v wget &> /dev/null; then
                wget -q --timeout=10 --tries=2 https://bootstrap.pypa.io/get-pip.py -O /tmp/get-pip.py 2>/dev/null || \
                curl -sS --connect-timeout 10 --max-time 30 https://bootstrap.pypa.io/get-pip.py -o /tmp/get-pip.py 2>/dev/null
            else
                curl -sS --connect-timeout 10 --max-time 30 https://bootstrap.pypa.io/get-pip.py -o /tmp/get-pip.py 2>/dev/null
            fi
            
            if [ -f /tmp/get-pip.py ]; then
                # 安装 pip（--user 避免权限问题，--quiet 静默输出）
                $PYTHON_SELECTED /tmp/get-pip.py --user --quiet &> /dev/null || log_warning "pip 安装失败"
                
                # 安装 setuptools（--user --no-warn-script-location --disable-pip-version-check 全自动）
                $PYTHON_SELECTED -m pip install --user --quiet --no-warn-script-location --disable-pip-version-check setuptools &> /dev/null || \
                log_warning "setuptools 安装失败"
                
                rm -f /tmp/get-pip.py
            else
                log_warning "无法下载 get-pip.py（网络问题）"
            fi
        fi
        SETUPTOOLS_INSTALL_SUCCESS=true
        
    else
        # 系统默认 Python 3（自动安装）
        if DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python3-setuptools python3-pip python3-dev 2>/dev/null; then
            SETUPTOOLS_INSTALL_SUCCESS=true
        else
            log_warning "setuptools 安装失败（可能包不可用）"
        fi
    fi
    
    # 验证 setuptools 安装
    if [ -n "$PYTHON_SELECTED" ] && $PYTHON_SELECTED -c "import setuptools" 2>/dev/null; then
        SETUPTOOLS_VERSION=$($PYTHON_SELECTED -c "import setuptools; print(setuptools.__version__)" 2>/dev/null)
        log_success "✅ setuptools 已安装: $SETUPTOOLS_VERSION"
        SETUPTOOLS_INSTALL_SUCCESS=true
    else
        log_warning "⚠️  setuptools 验证失败"
        SETUPTOOLS_INSTALL_SUCCESS=false
    fi
    
    # 如果是 Python 2.7 回退场景且安装失败，则切换到低版本 Python 3.9
    if [ "${PYTHON27_FALLBACK:-false}" = true ] && [ "$SETUPTOOLS_INSTALL_SUCCESS" = false ]; then
        log_warning "⚠️  Python 2.7 环境配置失败，执行回退方案..."
        log_info "正在安装低版本 Python 3.9（能兼容 Python 2 代码）..."
        
        # 确保 software-properties-common 已安装
        $SUDO apt-get install -y -qq software-properties-common &> /dev/null || true
        
        # 添加 PPA 并安装低版本 Python 3.9
        if DEBIAN_FRONTEND=noninteractive $SUDO add-apt-repository -y ppa:deadsnakes/ppa &> /dev/null; then
            log_info "✅ PPA 添加成功，更新软件源..."
            $SUDO apt-get update -qq &> /dev/null || $SUDO apt update -qq &> /dev/null
            
            # 安装低版本 Python 3.9（能兼容 Python 2 代码）
            if DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python3.9 python3.9-dev python3.9-distutils &> /dev/null; then
                log_success "✅ 低版本 Python 3.9 安装成功（能兼容 Python 2 代码）"
                PYTHON_SELECTED="/usr/bin/python3.9"
                PYTHON_VERSION_INFO="Python 3.9（Python 2.7 回退方案，能兼容 Python 2 代码）"
                
                # 重新创建软链接
                log_info "创建软链接: /usr/bin/python -> $PYTHON_SELECTED"
                if $SUDO ln -sf "$PYTHON_SELECTED" /usr/bin/python 2>/dev/null; then
                    log_success "✅ 软链接创建成功"
                    hash -r 2>/dev/null || true
                fi
                
                # 重新安装 setuptools
                log_info "为 Python 3.9 安装 setuptools..."
                DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python3.9-distutils &> /dev/null || true
                
                # 使用 pip 安装 setuptools
                if ! $PYTHON_SELECTED -c "import setuptools" 2>/dev/null; then
                    if command -v wget &> /dev/null; then
                        wget -q --timeout=10 --tries=2 https://bootstrap.pypa.io/get-pip.py -O /tmp/get-pip.py 2>/dev/null || \
                        curl -sS --connect-timeout 10 --max-time 30 https://bootstrap.pypa.io/get-pip.py -o /tmp/get-pip.py 2>/dev/null
                    else
                        curl -sS --connect-timeout 10 --max-time 30 https://bootstrap.pypa.io/get-pip.py -o /tmp/get-pip.py 2>/dev/null
                    fi
                    
                    if [ -f /tmp/get-pip.py ]; then
                        $PYTHON_SELECTED /tmp/get-pip.py --user --quiet &> /dev/null || true
                        $PYTHON_SELECTED -m pip install --user --quiet --no-warn-script-location --disable-pip-version-check setuptools &> /dev/null || true
                        rm -f /tmp/get-pip.py
                    fi
                fi
                
                # 验证 setuptools
                if $PYTHON_SELECTED -c "import setuptools" 2>/dev/null; then
                    SETUPTOOLS_VERSION=$($PYTHON_SELECTED -c "import setuptools; print(setuptools.__version__)" 2>/dev/null)
                    log_success "✅ setuptools 已安装: $SETUPTOOLS_VERSION"
                fi
            else
                log_error "❌ Python 3.9 安装失败"
                log_info "某些功能可能不可用"
            fi
        else
            log_error "❌ 无法添加 PPA，Python 环境配置失败"
            log_info "某些功能可能不可用"
        fi
    fi

    # 安装分布式编译工具（自动安装）
    log_info "安装分布式编译工具 (distcc)..."
    DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq distcc 2>/dev/null || \
    log_warning "distcc 安装失败（可选工具）"

    # 验证 distcc 安装
    if command -v distcc &> /dev/null && command -v distccd &> /dev/null; then
        log_success "distcc 安装成功"
        log_info "  - 客户端: $(distcc --version 2>&1 | head -n1)"
        log_info "  - 服务端: $(distccd --version 2>&1 | head -n1)"
    else
        log_warning "distcc 未正确安装"
    fi
    
    # 安装 icecc 客户端（如果配置为 icecc 模式）
    if [ -f "ci/distcc.conf" ]; then
        local distcc_mode=$(grep "^DISTCC_MODE=" ci/distcc.conf 2>/dev/null | cut -d'=' -f2 | tr -d '"' | tr -d "'" || echo "distcc")
        if [ "$distcc_mode" = "icecc" ]; then
            log_info "检测到 icecc 模式，自动安装 icecc 客户端..."
            DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq icecc 2>/dev/null || \
            log_warning "icecc 安装失败（可选工具）"
            
            if command -v icecc &> /dev/null; then
                log_success "icecc 客户端安装成功"
                log_info "  - 版本: $(icecc --version 2>&1 | head -n1)"
            else
                log_warning "icecc 未正确安装"
            fi
        fi
    fi

    # 安装 Google Protobuf Python 库
    log_info "安装 Google Protobuf Python 库..."
    
    # 在安装 protobuf 之前，确保 six 模块已安装（protobuf 需要 six>=1.9）
    if [ -n "$PYTHON_SELECTED" ]; then
        if echo "$PYTHON_SELECTED" | grep -q "python2.7"; then
            log_info "检查 six 模块（protobuf 依赖）..."
            if ! python2.7 -c "import six" 2>/dev/null; then
                log_warning "⚠️  six 模块未安装，protobuf 需要 six>=1.9，正在安装..."
                # 尝试使用 pip 安装
                if python2.7 -m pip --version &>/dev/null; then
                    if python2.7 -m pip install --user --quiet --no-warn-script-location --disable-pip-version-check "six>=1.9" &>/dev/null; then
                        log_success "✅ six 模块安装成功（通过 pip）"
                    else
                        log_warning "⚠️  通过 pip 安装 six 失败，尝试使用 apt-get..."
                        DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python-six 2>/dev/null || \
                        DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python2-six 2>/dev/null || \
                        log_warning "⚠️  six 模块安装失败"
                        
                        # 验证安装
                        if python2.7 -c "import six" 2>/dev/null; then
                            log_success "✅ six 模块安装成功（通过 apt-get）"
                        else
                            log_warning "⚠️  six 模块安装失败，protobuf 安装可能会失败"
                        fi
                    fi
                else
                    # pip 不可用，尝试使用 apt-get
                    DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python-six 2>/dev/null || \
                    DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq python2-six 2>/dev/null || \
                    log_warning "⚠️  six 模块安装失败"
                    
                    # 验证安装
                    if python2.7 -c "import six" 2>/dev/null; then
                        log_success "✅ six 模块安装成功（通过 apt-get）"
                    else
                        log_warning "⚠️  six 模块安装失败，protobuf 安装可能会失败"
                    fi
                fi
            else
                # 检查版本是否满足要求（>=1.9）
                SIX_VERSION=$(python2.7 -c "import six; print(six.__version__)" 2>/dev/null || echo "0.0.0")
                log_info "✅ six 模块已安装: $SIX_VERSION"
            fi
        fi
    fi
    
    local protobuf_python_dir="tools/google3.6/python"
    local protoc_dir="tools/google3.6/src"
    
    if [ -d "$protobuf_python_dir" ] && [ -f "$protobuf_python_dir/setup.py" ]; then
        # 确保 protoc 已复制到 src 目录
        if [ ! -f "$protoc_dir/protoc" ]; then
            log_info "复制 protoc 到 $protoc_dir..."
            if [ -f "tools/protoc" ]; then
                cp "tools/protoc" "$protoc_dir/protoc" &> /dev/null || true
                chmod +x "$protoc_dir/protoc" &> /dev/null || true
            fi
        fi
        
        # 编译并安装 Protobuf Python 库（静默输出）
        cd "$protobuf_python_dir" &> /dev/null || true
        
        log_info "编译 Protobuf Python 库..."
        BUILD_OUTPUT=$(mktemp /tmp/protobuf_build.XXXXXX 2>/dev/null || echo /tmp/protobuf_build.log)
        if $PYTHON_SELECTED setup.py build &> "$BUILD_OUTPUT"; then
            log_info "安装 Protobuf Python 库..."
            PROTOBUF_INSTALL_SUCCESS=false
            INSTALL_OUTPUT=$(mktemp /tmp/protobuf_install.XXXXXX 2>/dev/null || echo /tmp/protobuf_install.log)
            
            # 先尝试使用 --user 选项安装（不需要 sudo）
            if $PYTHON_SELECTED setup.py install --user &> "$INSTALL_OUTPUT"; then
                log_success "✅ Protobuf Python 库安装成功（用户目录）"
                PROTOBUF_INSTALL_SUCCESS=true
                rm -f "$INSTALL_OUTPUT" 2>/dev/null || true
            # 如果 --user 安装失败，尝试使用 sudo 安装到系统目录
            elif [ -n "$SUDO" ] && $SUDO $PYTHON_SELECTED setup.py install &> "$INSTALL_OUTPUT"; then
                log_success "✅ Protobuf Python 库安装成功（系统目录）"
                PROTOBUF_INSTALL_SUCCESS=true
                rm -f "$INSTALL_OUTPUT" 2>/dev/null || true
            else
                log_warning "⚠️  Protobuf Python 库安装失败"
                
                # 显示实际错误信息（最后几行）
                if [ -f "$INSTALL_OUTPUT" ]; then
                    log_info "安装错误信息："
                    tail -20 "$INSTALL_OUTPUT" | while IFS= read -r line; do
                        log_info "  $line"
                    done
                    rm -f "$INSTALL_OUTPUT" 2>/dev/null || true
                fi
                
                # 检查 six 模块是否可用
                if ! $PYTHON_SELECTED -c "import six" 2>/dev/null; then
                    log_warning "⚠️  检测到 six 模块未安装，这是 protobuf 的必需依赖"
                    log_info "请先安装 six 模块："
                    if $PYTHON_SELECTED -m pip --version &>/dev/null; then
                        log_info "  $PYTHON_SELECTED -m pip install --user six"
                    else
                        log_info "  $SUDO apt-get install -y python-six"
                    fi
                fi
                
                log_info ""
                log_info "可能的原因："
                log_info "  1. 缺少 six 模块（protobuf 依赖）"
                log_info "  2. 权限不足（需要 sudo 权限）"
                log_info "  3. 网络问题（无法下载依赖）"
                log_info ""
                log_info "手动安装命令："
                log_info "  cd $protobuf_python_dir"
                log_info "  $PYTHON_SELECTED setup.py install --user  # 安装到用户目录（推荐）"
                if [ -n "$SUDO" ]; then
                    log_info "  或: sudo $PYTHON_SELECTED setup.py install  # 安装到系统目录"
                fi
            fi
            rm -f "$BUILD_OUTPUT" 2>/dev/null || true
            
            # 清理构建临时文件
            if [ "$PROTOBUF_INSTALL_SUCCESS" = true ]; then
                $PYTHON_SELECTED setup.py clean --all &> /dev/null || true
            fi
        else
            log_warning "⚠️  Protobuf Python 库编译失败"
            log_info "可能的原因："
            log_info "  1. 缺少编译工具（gcc/g++）"
            log_info "  2. 缺少 six 模块（protobuf 依赖）"
            log_info "  3. Python 开发头文件缺失"
        fi
        
        # 返回原目录
        cd - &> /dev/null || true
    else
        log_warning "⚠️  未找到 Protobuf Python 源码 ($protobuf_python_dir)"
        log_info "跳过 Protobuf Python 库安装"
    fi
    
    log_success "基础构建工具安装完成"
    log_info ""
    log_info "分布式编译配置:"
    log_info "  1. 主编译机: 创建 ci/distcc.conf 配置文件"
    log_info "  2. 远程编译机: 运行 sudo ./ci/setup-distccd.sh"
    log_info "  3. 详细说明: docs/分布式编译指南.md"
}

# 安装依赖（CentOS/RHEL）
install_deps_centos() {
    log_info "检查并安装基础构建工具（CentOS/RHEL）..."

    # 检查是否需要 sudo
    SUDO=""
    if [ "$EUID" -ne 0 ]; then
        SUDO="sudo"
    fi

    # 安装基础构建工具（分批安装，避免某个包失败影响全部）
    # 项目依赖的开发库请根据实际需要手动安装或在 Makefile 中配置
    log_info "正在安装构建工具（完全自动，无需确认）..."
    
    # 分批安装，避免某个包失败影响全部
    # 1. 安装核心工具（必须成功）
    log_info "安装核心工具 (gcc, gcc-c++, make, git)..."
    
    # 显示安装过程和错误信息
    install_output=$(mktemp /tmp/yum_install.XXXXXX 2>/dev/null || echo /tmp/yum_install.log)
    if $SUDO yum install -y -q \
        gcc \
        gcc-c++ \
        make \
        git &> "$install_output"; then
        log_success "✅ 核心工具安装成功"
        rm -f "$install_output" 2>/dev/null || true
    else
        log_error "❌ 核心工具安装失败"
        log_info ""
        log_error "安装输出："
        if [ -f "$install_output" ] && [ -s "$install_output" ]; then
            tail -20 "$install_output" | while IFS= read -r line; do
                log_error "  $line"
            done
        fi
        log_info ""
        log_info "可能的原因："
        log_info "  1. 网络问题：无法连接软件源"
        log_info "  2. 软件源配置错误"
        log_info "  3. 磁盘空间不足"
        log_info "  4. 包依赖冲突"
        log_info ""
        log_info "建议操作："
        log_info "  1. 检查网络：ping mirror.centos.org"
        log_info "  2. 手动测试：sudo yum install -y gcc gcc-c++ make"
        log_info "  3. 检查磁盘空间：df -h"
        log_info "  4. 查看软件源：yum repolist"
        log_info ""
        rm -f "$install_output" 2>/dev/null || true
        return 1
    fi
    
    # 2. 安装构建工具（可选，但会在验证时补装）
    log_info "安装构建工具 (cmake3, ninja-build, ccache)..."
    $SUDO yum install -y -q \
        cmake3 \
        ninja-build \
        ccache &> /dev/null || \
        log_warning "⚠️  部分构建工具安装失败，稍后验证时补装..."
    
    # 2.5. 检测 CentOS/RHEL 版本，如果是 8+，启用 PowerTools/CodeReady Builder 仓库
    # 这些仓库包含 glibc-static 和 libstdc++-static 等包
    local centos_version=""
    local os_id=""
    if [ -f /etc/os-release ]; then
        . /etc/os-release
        os_id="$ID"
        if [[ "$os_id" == "centos" ]] || [[ "$os_id" == "rhel" ]]; then
            centos_version=$(echo "$VERSION_ID" | cut -d'.' -f1)
        fi
    fi
    
    if [[ "$centos_version" == "8" ]]; then
        log_info "检测到 CentOS/RHEL 8，尝试启用 PowerTools/CodeReady Builder 仓库..."
        
        # 确保 yum-config-manager 已安装
        if ! command -v yum-config-manager &> /dev/null; then
            log_info "未找到 yum-config-manager，正在自动安装 yum-utils..."
            if $SUDO yum install -y -q yum-utils 2>/dev/null; then
                log_success "✅ yum-utils 安装成功"
            else
                log_warning "⚠️  yum-utils 安装失败，尝试使用替代方法启用仓库"
            fi
        fi
        
        # 尝试启用 PowerTools/CodeReady Builder 仓库
        if command -v yum-config-manager &> /dev/null; then
            if [[ "$os_id" == "centos" ]]; then
                if $SUDO yum config-manager --set-enabled powertools &> /dev/null 2>&1 || \
                   $SUDO yum config-manager --set-enabled PowerTools &> /dev/null 2>&1; then
                    log_success "✅ PowerTools 仓库已启用"
                else
                    # 检查仓库是否已启用
                    if yum repolist enabled | grep -qi "powertools\|PowerTools"; then
                        log_info "✅ PowerTools 仓库已启用（之前已启用）"
                    else
                        log_warning "⚠️  PowerTools 仓库启用失败（可能仓库不存在或需要手动配置）"
                        log_info "可尝试手动执行: sudo yum config-manager --set-enabled powertools"
                    fi
                fi
            elif [[ "$os_id" == "rhel" ]]; then
                if $SUDO yum config-manager --set-enabled codeready-builder-for-rhel-8-rhui-rpms &> /dev/null 2>&1 || \
                   $SUDO subscription-manager repos --enable codeready-builder-for-rhel-8-rhui-rpms &> /dev/null 2>&1; then
                    log_success "✅ CodeReady Builder 仓库已启用"
                else
                    log_warning "⚠️  CodeReady Builder 仓库启用失败（可能已启用或不存在）"
                fi
            fi
        else
            # 如果 yum-config-manager 仍然不可用，尝试直接修改仓库配置文件
            log_warning "⚠️  yum-config-manager 不可用，尝试直接启用 PowerTools 仓库..."
            if [[ "$os_id" == "centos" ]]; then
                # 尝试使用 dnf config-manager（CentOS 8 可能使用 dnf）
                if command -v dnf &> /dev/null; then
                    if $SUDO dnf config-manager --set-enabled powertools &> /dev/null 2>&1 || \
                       $SUDO dnf config-manager --set-enabled PowerTools &> /dev/null 2>&1; then
                        log_success "✅ PowerTools 仓库已启用（通过 dnf）"
                    fi
                fi
            fi
        fi
    fi
    
    # 3. 安装 Python 和依赖（可选）
    local optional_packages=()
    
    # 检查 python2.7 是否已安装，如果已安装则跳过 python2 和 python2-devel
    if command -v python2.7 &> /dev/null || rpm -q python-2.7 &>/dev/null || rpm -q python2.7 &>/dev/null; then
        log_info "检测到 python2.7 已安装，跳过 python2 和 python2-devel 安装"
        optional_packages=("glibc-static" "libstdc++-static" "krb5-devel")
    else
        optional_packages=("python2" "python2-devel" "glibc-static" "libstdc++-static" "krb5-devel")
    fi
    
    local failed_packages=()
    local install_output=$(mktemp /tmp/yum_install.XXXXXX 2>/dev/null || echo /tmp/yum_install.log)
    
    # 尝试安装所有包，捕获输出
    if [ ${#optional_packages[@]} -gt 0 ]; then
        if ! $SUDO yum install -y -q "${optional_packages[@]}" &> "$install_output"; then
            # 检查哪些包安装失败
            for package in "${optional_packages[@]}"; do
                if ! rpm -q "$package" &>/dev/null; then
                    failed_packages+=("$package")
                fi
            done
            
            if [ ${#failed_packages[@]} -gt 0 ]; then
                log_warning "部分依赖安装失败（不影响核心功能）"
                log_info "失败的包："
                for package in "${failed_packages[@]}"; do
                    log_info "  - $package"
                done
                log_info ""
                
                # 检查是否是 glibc-static 或 libstdc++-static 失败
                local needs_powertools=false
                for package in "${failed_packages[@]}"; do
                    if [[ "$package" == "glibc-static" ]] || [[ "$package" == "libstdc++-static" ]]; then
                        needs_powertools=true
                        break
                    fi
                done
                
                if [ "$needs_powertools" = true ] && [[ "$centos_version" == "8" ]]; then
                    log_info "注意：glibc-static 和 libstdc++-static 在 CentOS/RHEL 8 中需要 PowerTools 仓库"
                    log_info "尝试启用 PowerTools 仓库并重新安装..."
                    
                    # 确保 yum-config-manager 已安装
                    if ! command -v yum-config-manager &> /dev/null; then
                        log_info "安装 yum-utils 以获取 yum-config-manager..."
                        $SUDO yum install -y -q yum-utils 2>/dev/null || true
                    fi
                    
                    # 重新读取 os-release 以获取 ID
                    local retry_os_id=""
                    if [ -f /etc/os-release ]; then
                        . /etc/os-release
                        retry_os_id="$ID"
                    fi
                    
                    # 尝试启用 PowerTools 仓库
                    local powertools_enabled=false
                    if command -v yum-config-manager &> /dev/null; then
                        if [[ "$retry_os_id" == "centos" ]]; then
                            if $SUDO yum config-manager --set-enabled powertools &> /dev/null 2>&1 || \
                               $SUDO yum config-manager --set-enabled PowerTools &> /dev/null 2>&1; then
                                powertools_enabled=true
                                log_success "✅ PowerTools 仓库已启用"
                            elif yum repolist enabled | grep -qi "powertools\|PowerTools"; then
                                powertools_enabled=true
                                log_info "✅ PowerTools 仓库已启用（之前已启用）"
                            fi
                        fi
                    elif command -v dnf &> /dev/null; then
                        if [[ "$retry_os_id" == "centos" ]]; then
                            if $SUDO dnf config-manager --set-enabled powertools &> /dev/null 2>&1 || \
                               $SUDO dnf config-manager --set-enabled PowerTools &> /dev/null 2>&1; then
                                powertools_enabled=true
                                log_success "✅ PowerTools 仓库已启用（通过 dnf）"
                            fi
                        fi
                    fi
                    
                    # 如果启用了仓库，更新缓存并重新尝试安装
                    if [ "$powertools_enabled" = true ]; then
                        log_info "更新软件源缓存..."
                        $SUDO yum makecache fast &> /dev/null || $SUDO yum makecache &> /dev/null || true
                    fi
                    
                    # 重新尝试安装失败的包
                    local retry_packages=()
                    for package in "${failed_packages[@]}"; do
                        if [[ "$package" == "glibc-static" ]] || [[ "$package" == "libstdc++-static" ]]; then
                            retry_packages+=("$package")
                        fi
                    done
                    if [ ${#retry_packages[@]} -gt 0 ]; then
                        log_info "重新尝试安装: ${retry_packages[*]}"
                        if $SUDO yum install -y -q "${retry_packages[@]}" 2>/dev/null; then
                            log_success "✅ ${retry_packages[*]} 安装成功（启用 PowerTools 后）"
                            # 从失败列表中移除已成功安装的包
                            local new_failed_packages=()
                            for package in "${failed_packages[@]}"; do
                                local is_retry_pkg=false
                                for retry_pkg in "${retry_packages[@]}"; do
                                    if [[ "$package" == "$retry_pkg" ]]; then
                                        is_retry_pkg=true
                                        break
                                    fi
                                done
                                if [ "$is_retry_pkg" = false ]; then
                                    new_failed_packages+=("$package")
                                fi
                            done
                            failed_packages=("${new_failed_packages[@]}")
                        else
                            log_warning "⚠️  即使启用 PowerTools 仓库后，${retry_packages[*]} 仍然安装失败"
                        fi
                    fi
                fi
                
                log_info "可能的原因："
                log_info "  1. 软件源中不存在该包"
                log_info "  2. 包名在不同 CentOS/RHEL 版本中不同"
                log_info "  3. 需要启用额外的软件源（如 EPEL、PowerTools）"
                log_info ""
                log_info "如需手动安装，可尝试："
                log_info "  $SUDO yum install -y ${failed_packages[*]}"
                
                # 显示 yum 的错误输出（最后几行），过滤掉已安装的包的提示
                if [ -f "$install_output" ] && [ -s "$install_output" ]; then
                    log_info "安装错误详情："
                    tail -10 "$install_output" | grep -v "已安装并且是最新版本" | grep -v "^$" | while IFS= read -r line; do
                        log_info "  $line"
                    done
                fi
            fi
        fi
    fi
    rm -f "$install_output" 2>/dev/null || true
    
    log_success "✅ 基础工具安装完成"

    # 验证关键工具是否安装成功
    log_info "验证编译工具链..."
    local missing_tools=()
    
    if ! command -v gcc &> /dev/null; then
        missing_tools+=("gcc")
    fi
    
    if ! command -v g++ &> /dev/null; then
        missing_tools+=("g++")
    fi
    
    if ! command -v make &> /dev/null; then
        missing_tools+=("make")
    fi
    
    if [ ${#missing_tools[@]} -gt 0 ]; then
        log_error "❌ 关键编译工具未安装: ${missing_tools[*]}"
        log_info ""
        log_info "解决方案："
        log_info "  1. 手动安装："
        log_info "     sudo yum install -y gcc gcc-c++ make"
        log_info ""
        log_info "  2. 检查仓库："
        log_info "     yum repolist"
        log_info ""
        log_info "  3. 如果使用 CentOS/RHEL 8+，确保启用 PowerTools/CodeReady Builder："
        log_info "     sudo yum config-manager --set-enabled powertools  # CentOS 8"
        log_info "     sudo yum config-manager --set-enabled codeready-builder-for-rhel-8-rhui-rpms  # RHEL 8"
        return 1
    fi
    
    log_success "✅ 编译工具链验证通过"
    log_info "  - gcc: $(gcc --version 2>&1 | head -n1)"
    log_info "  - g++: $(g++ --version 2>&1 | head -n1)"
    log_info "  - make: $(make --version 2>&1 | head -n1)"
    
    # 验证 cmake（未安装则自动安装）
    local cmake_has_error=false
    if command -v cmake &> /dev/null; then
        # 测试 cmake 是否能正常运行（检测符号错误）
        if ! cmake --version &> /dev/null 2>&1; then
            cmake_error_output=$(cmake --version 2>&1)
            if echo "$cmake_error_output" | grep -q "symbol lookup error\|undefined symbol"; then
                log_warning "⚠️  cmake 存在符号错误: $cmake_error_output"
                cmake_has_error=true
            fi
        fi
        if [ "$cmake_has_error" = false ]; then
            log_success "✅ cmake 已安装: $(cmake --version 2>&1 | head -n1)"
        fi
    elif command -v cmake3 &> /dev/null; then
        # 测试 cmake3 是否能正常运行（检测符号错误）
        if ! cmake3 --version &> /dev/null 2>&1; then
            cmake_error_output=$(cmake3 --version 2>&1)
            if echo "$cmake_error_output" | grep -q "symbol lookup error\|undefined symbol"; then
                log_warning "⚠️  cmake3 存在符号错误: $cmake_error_output"
                cmake_has_error=true
            fi
        fi
        if [ "$cmake_has_error" = false ]; then
            log_success "✅ cmake3 已安装: $(cmake3 --version 2>&1 | head -n1)"
            log_info "（将在后续步骤中创建 cmake -> cmake3 软链接）"
        fi
    fi
    
    # 如果 cmake/cmake3 存在符号错误，尝试修复
    if [ "$cmake_has_error" = true ]; then
        log_warning "⚠️  检测到 cmake 符号错误，尝试自动修复..."
        log_info "步骤 1: 更新 libarchive 库..."
        if $SUDO yum update -y -q libarchive 2>/dev/null; then
            log_success "✅ libarchive 更新成功"
        else
            log_warning "⚠️  libarchive 更新失败（可能已是最新版本）"
        fi
        
        log_info "步骤 2: 重新安装 cmake3..."
        if command -v cmake &> /dev/null; then
            $SUDO yum remove -y -q cmake 2>/dev/null || true
        fi
        if command -v cmake3 &> /dev/null; then
            $SUDO yum remove -y -q cmake3 2>/dev/null || true
        fi
        
        # 重新安装 cmake3
        if $SUDO yum install -y -q cmake3 2>/dev/null; then
            # 测试 cmake3 是否能正常运行
            if cmake3 --version &> /dev/null 2>&1; then
                log_success "✅ cmake3 重新安装成功: $(cmake3 --version 2>&1 | head -n1)"
                cmake_has_error=false
            else
                # 如果重新安装后仍有问题，尝试使用 reinstall
                log_warning "⚠️  cmake3 重新安装后仍有问题，尝试使用 reinstall..."
                if $SUDO yum reinstall -y -q cmake3 2>/dev/null; then
                    if cmake3 --version &> /dev/null 2>&1; then
                        log_success "✅ cmake3 reinstall 成功: $(cmake3 --version 2>&1 | head -n1)"
                        cmake_has_error=false
                    else
                        log_error "❌ cmake3 reinstall 后仍有问题"
                        cmake_has_error=true
                    fi
                else
                    log_error "❌ cmake3 reinstall 失败"
                    cmake_has_error=true
                fi
            fi
        else
            log_error "❌ cmake3 重新安装失败"
            cmake_has_error=true
        fi
    fi
    
    # 如果仍然没有可用的 cmake，尝试安装
    if [ "$cmake_has_error" = false ] && ! command -v cmake &> /dev/null && ! command -v cmake3 &> /dev/null; then
        log_warning "⚠️  cmake 未安装，尝试自动安装 cmake3..."
        if $SUDO yum install -y -q cmake3 &> /dev/null; then
            if cmake3 --version &> /dev/null 2>&1; then
                log_success "✅ cmake3 安装成功: $(cmake3 --version 2>&1 | head -n1)"
            else
                log_error "❌ cmake3 安装后无法运行"
                log_info "请手动安装: sudo yum install cmake3"
                return 1
            fi
        else
            log_error "❌ cmake3 安装失败"
            log_info "请手动安装: sudo yum install cmake3"
            return 1
        fi
    fi
    
    # 如果仍有错误，给出建议
    if [ "$cmake_has_error" = true ]; then
        log_warning "⚠️  cmake 符号错误修复失败"
        log_info "已尝试的修复步骤："
        log_info "  1. ✅ 更新 libarchive 库"
        log_info "  2. ✅ 重新安装 cmake3"
        log_info "  3. ✅ 使用 reinstall 重新安装 cmake3"
        log_info ""
        log_info "建议手动检查："
        log_info "  1. 检查库依赖: ldd $(which cmake3 2>/dev/null || which cmake 2>/dev/null)"
        log_info "  2. 检查 libarchive 版本: rpm -q libarchive"
        log_info "  3. 检查 cmake3 版本: rpm -q cmake3"
        log_info "  4. 可能需要更新整个系统: sudo yum update -y"
    fi
    
    # 验证 ninja（未安装则自动安装）
    if command -v ninja &> /dev/null || command -v ninja-build &> /dev/null; then
        log_success "✅ Ninja 构建工具已安装（更快、输出更清晰）"
    else
        log_warning "⚠️  Ninja 未安装，尝试自动安装..."
        if $SUDO yum install -y -q ninja-build &> /dev/null; then
            log_success "✅ Ninja 安装成功"
        else
            log_warning "⚠️  Ninja 安装失败（可选工具，不影响构建）"
            log_info "推荐手动安装: sudo yum install ninja-build"
        fi
    fi

    # 验证并安装 Clang 编译器（可选，用于提速编译）
    if command -v clang &> /dev/null; then
        log_success "✅ Clang 编译器已安装: $(clang --version 2>&1 | head -n1)"
    else
        log_info "检测到系统未安装 Clang 编译器（可选）"
        log_info "Clang 编译器通常比 GCC 编译速度快 10-20%"
        log_info "正在自动安装 Clang..."
        
        # 尝试安装 clang
        if $SUDO yum install -y -q clang lldb lld 2>/dev/null; then
            log_success "✅ Clang 安装成功"
            log_info "  - Clang: $(clang --version 2>&1 | head -n1)"
            log_info "  - Linux 上默认已启用 Clang，如需使用 GCC: export USE_CLANG=0"
        else
            log_warning "⚠️  Clang 安装失败（可选工具，不影响构建，将使用 GCC）"
            log_info "推荐手动安装: sudo yum install clang"
        fi
    fi

    # 检查 Python 命令并创建软链接（仅支持 Python 2.7）
    log_info "检查 Python 环境..."
    
    PYTHON_SELECTED=""
    PYTHON_VERSION_INFO=""
    
    # 检查 python2.7 是否存在
    if command -v python2.7 &> /dev/null; then
        PYTHON_SELECTED=$(which python2.7)
        PYTHON_VERSION_INFO="Python 2.7"
        log_info "✅ 检测到 python2.7: $PYTHON_SELECTED"
    elif command -v python2 &> /dev/null; then
        PYTHON_SELECTED=$(which python2)
        PYTHON_VERSION_INFO="Python 2"
        log_info "✅ 检测到 python2: $PYTHON_SELECTED"
    elif command -v python &> /dev/null; then
        # 检查现有 python 是否是 Python 2
        local python_version=$(python --version 2>&1 | grep -oP 'Python \K[0-9]+' | head -n1)
        if [ "$python_version" = "2" ]; then
            PYTHON_SELECTED=$(which python)
            PYTHON_VERSION_INFO="Python 2（系统默认）"
            log_info "✅ 检测到系统默认 Python 2: $PYTHON_SELECTED"
        else
            log_warning "⚠️  检测到系统 python 不是 Python 2，版本: $python_version"
            log_info "正在自动安装 Python 2.7..."
            if $SUDO yum install -y -q python2 python2-devel 2>/dev/null; then
                # 重新检查安装后的 Python 2
                if command -v python2.7 &> /dev/null; then
                    PYTHON_SELECTED=$(which python2.7)
                    PYTHON_VERSION_INFO="Python 2.7（自动安装）"
                    log_success "✅ Python 2.7 安装成功: $PYTHON_SELECTED"
                elif command -v python2 &> /dev/null; then
                    PYTHON_SELECTED=$(which python2)
                    PYTHON_VERSION_INFO="Python 2（自动安装）"
                    log_success "✅ Python 2 安装成功: $PYTHON_SELECTED"
                else
                    log_warning "⚠️  Python 2 安装后仍无法找到，请手动安装: sudo yum install -y python2 python2-devel"
                fi
            else
                log_warning "⚠️  Python 2 自动安装失败"
                log_info "请手动安装: sudo yum install -y python2 python2-devel"
            fi
        fi
    else
        log_warning "⚠️  未找到 Python 2"
        log_info "正在自动安装 Python 2.7..."
        if $SUDO yum install -y -q python2 python2-devel 2>/dev/null; then
            # 重新检查安装后的 Python 2
            if command -v python2.7 &> /dev/null; then
                PYTHON_SELECTED=$(which python2.7)
                PYTHON_VERSION_INFO="Python 2.7（自动安装）"
                log_success "✅ Python 2.7 安装成功: $PYTHON_SELECTED"
            elif command -v python2 &> /dev/null; then
                PYTHON_SELECTED=$(which python2)
                PYTHON_VERSION_INFO="Python 2（自动安装）"
                log_success "✅ Python 2 安装成功: $PYTHON_SELECTED"
            else
                log_warning "⚠️  Python 2 安装后仍无法找到，请手动安装: sudo yum install -y python2 python2-devel"
            fi
        else
            log_warning "⚠️  Python 2 自动安装失败"
            log_info "请手动安装: sudo yum install -y python2 python2-devel"
        fi
    fi
    
    # 创建软链接到选定的 Python 版本
    if [ -n "$PYTHON_SELECTED" ]; then
        log_info "================================================"
        log_success "选定 Python: $PYTHON_VERSION_INFO"
        log_info "路径: $PYTHON_SELECTED"
        log_info "================================================"
        
        # 检查是否需要创建软链接
        if [ ! -e /usr/bin/python ] || [ "$(readlink -f /usr/bin/python 2>/dev/null)" != "$PYTHON_SELECTED" ]; then
            log_info "创建软链接: /usr/bin/python -> $PYTHON_SELECTED"
            if $SUDO ln -sf "$PYTHON_SELECTED" /usr/bin/python 2>/dev/null; then
                log_success "✅ 软链接创建成功"
                hash -r 2>/dev/null || true
            else
                log_warning "⚠️  无法创建软链接（权限不足）"
                log_info "请手动执行: sudo ln -sf $PYTHON_SELECTED /usr/bin/python"
            fi
        else
            log_info "✅ python 命令已正确指向: $PYTHON_SELECTED"
        fi
        
        # 显示最终的 Python 版本
        if command -v python &> /dev/null; then
            log_info "当前 python 版本: $(python --version 2>&1)"
        fi
    fi

    # 安装分布式编译工具
    log_info "安装分布式编译工具 (distcc)..."
    $SUDO yum install -y -q distcc || log_warning "distcc 安装失败"

    # 验证 distcc 安装
    if rpm -q distcc &> /dev/null; then
        log_success "distcc 安装成功"
        local distccd_path=$(which distccd 2>/dev/null || find /usr -name distccd 2>/dev/null | head -n1)
        if [ -n "$distccd_path" ]; then
            log_info "  - distccd 路径: $distccd_path"
            log_info "  - 版本: $(rpm -q distcc)"
        fi
        if command -v distcc &> /dev/null; then
            log_info "  - 客户端: $(distcc --version 2>&1 | head -n1)"
        fi
    else
        log_warning "distcc 未正确安装"
    fi
    
    # 安装 icecc 客户端（如果配置为 icecc 模式）
    if [ -f "ci/distcc.conf" ]; then
        local distcc_mode=$(grep "^DISTCC_MODE=" ci/distcc.conf 2>/dev/null | cut -d'=' -f2 | tr -d '"' | tr -d "'" || echo "distcc")
        if [ "$distcc_mode" = "icecc" ]; then
            log_info "检测到 icecc 模式，安装 icecc 客户端..."
            
            # 确保 EPEL 仓库已安装（完全自动化）
            if ! yum repolist | grep -q epel; then
                log_info "自动安装 EPEL 仓库..."
                # -y 自动确认，-q 静默输出
                $SUDO yum install -y -q epel-release &> /dev/null || log_warning "EPEL 安装失败"
                # 更新缓存（静默）
                $SUDO yum makecache fast &> /dev/null || $SUDO yum makecache &> /dev/null || true
            fi
            
            # CentOS/RHEL 的包名是 icecream（自动安装）
            log_info "安装 icecc 客户端..."
            $SUDO yum install -y -q icecream &> /dev/null || log_warning "icecc 安装失败（可选工具）"
            
            if command -v icecc &> /dev/null; then
                log_success "icecc 客户端安装成功"
                log_info "  - 版本: $(icecc --version 2>&1 | head -n1)"
            else
                log_warning "icecc 未正确安装，将回退到 distcc 模式"
            fi
        fi
    fi

    # 检查 cmake 版本，如果过低且 cmake3 存在，自动创建软链接
    CMAKE_NEED_FIX=0
    if command -v cmake &> /dev/null; then
        CMAKE_VERSION=$(cmake --version 2>/dev/null | head -n1 | grep -oP '\d+\.\d+' | head -n1)
        if [ -n "$CMAKE_VERSION" ]; then
            CMAKE_MAJOR=$(echo $CMAKE_VERSION | cut -d. -f1)
            CMAKE_MINOR=$(echo $CMAKE_VERSION | cut -d. -f2)
            if [ "$CMAKE_MAJOR" -lt 3 ] || ([ "$CMAKE_MAJOR" -eq 3 ] && [ "$CMAKE_MINOR" -lt 10 ]); then
                CMAKE_NEED_FIX=1
            fi
        fi
    else
        # cmake 命令不存在
        CMAKE_NEED_FIX=1
    fi

    # 如果需要修复且 cmake3 存在，自动创建软链接
    if [ "$CMAKE_NEED_FIX" -eq 1 ] && command -v cmake3 &> /dev/null; then
        CMAKE3_PATH=$(which cmake3)
        log_info "检测到 cmake 版本过低或不存在，自动创建 cmake -> cmake3 软链接..."
        if $SUDO ln -sf "$CMAKE3_PATH" /usr/bin/cmake 2>/dev/null; then
            log_success "已创建软链接: /usr/bin/cmake -> $CMAKE3_PATH"
            # 清除 shell 命令缓存
            hash -r 2>/dev/null || true
            # 验证
            NEW_CMAKE_VERSION=$(cmake --version 2>/dev/null | head -n1 | grep -oP '\d+\.\d+\.\d+' | head -n1)
            if [ -n "$NEW_CMAKE_VERSION" ]; then
                log_success "cmake 版本已更新: $NEW_CMAKE_VERSION"
            fi
        else
            log_warning "无法创建 cmake 软链接（权限不足）"
            log_info "请手动执行: sudo ln -sf $CMAKE3_PATH /usr/bin/cmake"
        fi
    fi

    # 安装 setuptools（仅支持 Python 2）
    log_info "安装 Python setuptools..."
    
    SETUPTOOLS_INSTALL_SUCCESS=false
    
    if [ -n "$PYTHON_SELECTED" ]; then
        # 安装 Python 2 setuptools
        if $SUDO yum install -y -q python2-setuptools python2-devel 2>/dev/null; then
            SETUPTOOLS_INSTALL_SUCCESS=true
        else
            log_warning "Python 2 setuptools 安装失败（可能包不可用）"
        fi
        
        # 检查并安装 six 模块（Python 2 需要）
        log_info "检查 Python 2 six 模块..."
        local python_cmd="$PYTHON_SELECTED"
        if ! $python_cmd -c "import six" 2>/dev/null; then
            log_warning "⚠️  six 模块未安装，正在安装..."
            # 尝试使用 pip 安装
            if $python_cmd -m pip --version &>/dev/null; then
                if $python_cmd -m pip install --user --quiet --no-warn-script-location --disable-pip-version-check six &>/dev/null; then
                    log_success "✅ six 模块安装成功（通过 pip）"
                else
                    log_warning "⚠️  通过 pip 安装 six 失败，尝试使用 yum..."
                    # 尝试使用 yum 安装
                    $SUDO yum install -y -q python-six 2>/dev/null || \
                    $SUDO yum install -y -q python2-six 2>/dev/null || \
                    log_warning "⚠️  six 模块安装失败（可能需要手动安装）"
                    
                    # 验证安装
                    if $python_cmd -c "import six" 2>/dev/null; then
                        log_success "✅ six 模块安装成功（通过 yum）"
                    else
                        log_warning "⚠️  six 模块安装失败，某些功能可能不可用"
                        log_info "  手动安装命令: $python_cmd -m pip install --user six"
                    fi
                fi
            else
                # pip 不可用，尝试使用 yum
                log_info "pip 不可用，尝试使用 yum 安装 six..."
                $SUDO yum install -y -q python-six 2>/dev/null || \
                $SUDO yum install -y -q python2-six 2>/dev/null || \
                log_warning "⚠️  six 模块安装失败（可能需要手动安装）"
                
                # 验证安装
                if $python_cmd -c "import six" 2>/dev/null; then
                    log_success "✅ six 模块安装成功（通过 yum）"
                else
                    log_warning "⚠️  six 模块安装失败，某些功能可能不可用"
                    log_info "  手动安装命令: $python_cmd -m pip install --user six"
                fi
            fi
        else
            SIX_VERSION=$($python_cmd -c "import six; print(six.__version__)" 2>/dev/null || echo "已安装")
            log_success "✅ six 模块已安装: $SIX_VERSION"
        fi
    fi
    
    # 验证 setuptools 安装
    if [ -n "$PYTHON_SELECTED" ] && $PYTHON_SELECTED -c "import setuptools" 2>/dev/null; then
        SETUPTOOLS_VERSION=$($PYTHON_SELECTED -c "import setuptools; print(setuptools.__version__)" 2>/dev/null)
        log_success "✅ setuptools 已安装: $SETUPTOOLS_VERSION"
        SETUPTOOLS_INSTALL_SUCCESS=true
    else
        log_warning "⚠️  setuptools 验证失败"
        SETUPTOOLS_INSTALL_SUCCESS=false
    fi

    # 安装 Google Protobuf Python 库
    log_info "安装 Google Protobuf Python 库..."
    
    # 在安装 protobuf 之前，确保 six 模块已安装（protobuf 需要 six>=1.9）
    if [ -n "$PYTHON_SELECTED" ]; then
        log_info "检查 six 模块（protobuf 依赖）..."
        if ! $PYTHON_SELECTED -c "import six" 2>/dev/null; then
            log_warning "⚠️  six 模块未安装，protobuf 需要 six>=1.9，正在安装..."
            # 尝试使用 pip 安装
            if $PYTHON_SELECTED -m pip --version &>/dev/null; then
                if $PYTHON_SELECTED -m pip install --user --quiet --no-warn-script-location --disable-pip-version-check "six>=1.9" &>/dev/null; then
                    log_success "✅ six 模块安装成功（通过 pip）"
                else
                    log_warning "⚠️  通过 pip 安装 six 失败，尝试使用 yum..."
                    $SUDO yum install -y -q python-six 2>/dev/null || \
                    $SUDO yum install -y -q python2-six 2>/dev/null || \
                    log_warning "⚠️  six 模块安装失败"
                    
                    # 验证安装
                    if $PYTHON_SELECTED -c "import six" 2>/dev/null; then
                        log_success "✅ six 模块安装成功（通过 yum）"
                    else
                        log_warning "⚠️  six 模块安装失败，protobuf 安装可能会失败"
                    fi
                fi
            else
                # pip 不可用，尝试使用 yum
                $SUDO yum install -y -q python-six 2>/dev/null || \
                $SUDO yum install -y -q python2-six 2>/dev/null || \
                log_warning "⚠️  six 模块安装失败"
                
                # 验证安装
                if $PYTHON_SELECTED -c "import six" 2>/dev/null; then
                    log_success "✅ six 模块安装成功（通过 yum）"
                else
                    log_warning "⚠️  six 模块安装失败，protobuf 安装可能会失败"
                fi
            fi
        else
            # 检查版本是否满足要求（>=1.9）
            SIX_VERSION=$($PYTHON_SELECTED -c "import six; print(six.__version__)" 2>/dev/null || echo "0.0.0")
            log_info "✅ six 模块已安装: $SIX_VERSION"
        fi
    fi
    
    local protobuf_python_dir="tools/google3.6/python"
    local protoc_dir="tools/google3.6/src"
    
    if [ -d "$protobuf_python_dir" ] && [ -f "$protobuf_python_dir/setup.py" ]; then
        # 确保 protoc 已复制到 src 目录
        if [ ! -f "$protoc_dir/protoc" ]; then
            log_info "复制 protoc 到 $protoc_dir..."
            if [ -f "tools/protoc" ]; then
                cp "tools/protoc" "$protoc_dir/protoc" &> /dev/null || true
                chmod +x "$protoc_dir/protoc" &> /dev/null || true
            fi
        fi
        
        # 编译并安装 Protobuf Python 库（静默输出）
        cd "$protobuf_python_dir" &> /dev/null || true
        
        # 检查是否已安装旧版本的 protobuf，如果版本不匹配则先卸载
        log_info "检查已安装的 Protobuf 版本..."
        if $PYTHON_SELECTED -c "import google.protobuf" 2>/dev/null; then
            local installed_version=$($PYTHON_SELECTED -c "import google.protobuf; print(google.protobuf.__version__)" 2>/dev/null || echo "")
            log_info "检测到已安装的 Protobuf 版本: $installed_version"
            
            # 如果版本是 3.6.x，直接使用，不需要卸载
            if [ -n "$installed_version" ]; then
                if echo "$installed_version" | grep -qE "^3\.6\."; then
                    log_success "✅ 已安装 Protobuf 3.6.x 版本 ($installed_version)，无需卸载，直接使用"
                    # 跳过后续安装步骤，直接返回原目录并退出
                    cd - &> /dev/null || true
                    return 0
                else
                    # 如果版本不是 3.6.x，尝试卸载
                    log_info "检测到非 3.6.x 版本 ($installed_version)，尝试卸载旧版本以避免冲突..."
                    $PYTHON_SELECTED -m pip uninstall -y protobuf 2>/dev/null || \
                    $PYTHON_SELECTED -c "import pkg_resources; pkg_resources.get_distribution('protobuf').uninstall()" 2>/dev/null || \
                    log_warning "无法卸载旧版本，继续尝试安装..."
                fi
            fi
        fi
        
        # 升级 setuptools 以避免兼容性问题
        log_info "检查并升级 setuptools（避免安装错误）..."
        if $PYTHON_SELECTED -m pip --version &>/dev/null; then
            # 尝试升级 setuptools 到较新版本（但不要太新，避免与旧 Python 2.7 不兼容）
            $PYTHON_SELECTED -m pip install --user --quiet --upgrade "setuptools<45" 2>/dev/null || \
            $PYTHON_SELECTED -m pip install --user --quiet --upgrade "setuptools<40" 2>/dev/null || \
            log_warning "setuptools 升级失败，继续尝试安装..."
        fi
        
        log_info "编译 Protobuf Python 库..."
        BUILD_OUTPUT=$(mktemp /tmp/protobuf_build.XXXXXX 2>/dev/null || echo /tmp/protobuf_build.log)
        if [ -n "$PYTHON_SELECTED" ] && $PYTHON_SELECTED setup.py build &> "$BUILD_OUTPUT"; then
            log_info "安装 Protobuf Python 库..."
            PROTOBUF_INSTALL_SUCCESS=false
            INSTALL_OUTPUT=$(mktemp /tmp/protobuf_install.XXXXXX 2>/dev/null || echo /tmp/protobuf_install.log)
            
            # 方法1：尝试使用 pip 安装（推荐，更可靠）
            if $PYTHON_SELECTED -m pip --version &>/dev/null; then
                log_info "使用 pip 安装 Protobuf Python 库..."
                if $PYTHON_SELECTED -m pip install --user --quiet --no-warn-script-location --disable-pip-version-check . &> "$INSTALL_OUTPUT"; then
                    log_success "✅ Protobuf Python 库安装成功（通过 pip，用户目录）"
                    PROTOBUF_INSTALL_SUCCESS=true
                    rm -f "$INSTALL_OUTPUT" 2>/dev/null || true
                elif [ -n "$SUDO" ] && $SUDO $PYTHON_SELECTED -m pip install --quiet --no-warn-script-location --disable-pip-version-check . &> "$INSTALL_OUTPUT"; then
                    log_success "✅ Protobuf Python 库安装成功（通过 pip，系统目录）"
                    PROTOBUF_INSTALL_SUCCESS=true
                    rm -f "$INSTALL_OUTPUT" 2>/dev/null || true
                else
                    log_warning "⚠️  通过 pip 安装失败，尝试使用 setup.py..."
                fi
            fi
            
            # 方法2：如果 pip 安装失败，尝试使用 setup.py install --single-version-externally-managed
            if [ "$PROTOBUF_INSTALL_SUCCESS" = false ]; then
                log_info "使用 setup.py 安装 Protobuf Python 库..."
                # 先尝试使用 --user 选项安装（不需要 sudo）
                if $PYTHON_SELECTED setup.py install --user --single-version-externally-managed --record /dev/null &> "$INSTALL_OUTPUT"; then
                    log_success "✅ Protobuf Python 库安装成功（用户目录）"
                    PROTOBUF_INSTALL_SUCCESS=true
                    rm -f "$INSTALL_OUTPUT" 2>/dev/null || true
                # 如果 --user 安装失败，尝试使用 sudo 安装到系统目录
                elif [ -n "$SUDO" ] && $SUDO $PYTHON_SELECTED setup.py install --single-version-externally-managed --record /dev/null &> "$INSTALL_OUTPUT"; then
                    log_success "✅ Protobuf Python 库安装成功（系统目录）"
                    PROTOBUF_INSTALL_SUCCESS=true
                    rm -f "$INSTALL_OUTPUT" 2>/dev/null || true
                # 如果 --single-version-externally-managed 失败，尝试传统方法
                elif $PYTHON_SELECTED setup.py install --user &> "$INSTALL_OUTPUT"; then
                    log_success "✅ Protobuf Python 库安装成功（用户目录，传统方法）"
                    PROTOBUF_INSTALL_SUCCESS=true
                    rm -f "$INSTALL_OUTPUT" 2>/dev/null || true
                elif [ -n "$SUDO" ] && $SUDO $PYTHON_SELECTED setup.py install &> "$INSTALL_OUTPUT"; then
                    log_success "✅ Protobuf Python 库安装成功（系统目录，传统方法）"
                    PROTOBUF_INSTALL_SUCCESS=true
                    rm -f "$INSTALL_OUTPUT" 2>/dev/null || true
                else
                    log_warning "⚠️  Protobuf Python 库安装失败"
                    
                    # 显示实际错误信息（最后几行）
                    if [ -f "$INSTALL_OUTPUT" ]; then
                        log_info "安装错误信息："
                        tail -30 "$INSTALL_OUTPUT" | while IFS= read -r line; do
                            log_info "  $line"
                        done
                        rm -f "$INSTALL_OUTPUT" 2>/dev/null || true
                    fi
                    
                    # 检查是否是 setuptools 版本问题
                    if grep -q "TypeError.*__init__.*takes exactly.*arguments" "$INSTALL_OUTPUT" 2>/dev/null; then
                        log_warning "⚠️  检测到 setuptools 版本兼容性问题"
                        log_info "解决方案："
                        log_info "  1. 升级 setuptools: $PYTHON_SELECTED -m pip install --user --upgrade 'setuptools<45'"
                        log_info "  2. 或使用 pip 安装: cd $protobuf_python_dir && $PYTHON_SELECTED -m pip install --user ."
                    fi
                    
                    # 检查 six 模块是否可用
                    if ! $PYTHON_SELECTED -c "import six" 2>/dev/null; then
                        log_warning "⚠️  检测到 six 模块未安装，这是 protobuf 的必需依赖"
                        log_info "请先安装 six 模块："
                        if $PYTHON_SELECTED -m pip --version &>/dev/null; then
                            log_info "  $PYTHON_SELECTED -m pip install --user six"
                        else
                            log_info "  $SUDO yum install -y python-six"
                        fi
                    fi
                    
                    log_info ""
                    log_info "可能的原因："
                    log_info "  1. setuptools 版本过旧（需要升级）"
                    log_info "  2. 缺少 six 模块（protobuf 依赖）"
                    log_info "  3. 已安装的 protobuf 版本冲突"
                    log_info "  4. 权限不足（需要 sudo 权限）"
                    log_info ""
                    log_info "手动安装命令："
                    log_info "  cd $protobuf_python_dir"
                    log_info "  $PYTHON_SELECTED -m pip install --user .  # 使用 pip 安装（推荐）"
                    log_info "  或: $PYTHON_SELECTED setup.py install --user --single-version-externally-managed --record /dev/null"
                    if [ -n "$SUDO" ]; then
                        log_info "  或: sudo $PYTHON_SELECTED setup.py install --single-version-externally-managed --record /dev/null"
                    fi
                fi
            fi
            rm -f "$BUILD_OUTPUT" 2>/dev/null || true
            
            # 清理构建临时文件
            if [ "$PROTOBUF_INSTALL_SUCCESS" = true ]; then
                $PYTHON_SELECTED setup.py clean --all &> /dev/null || true
            fi
        else
            log_warning "⚠️  Protobuf Python 库编译失败"
            log_info "可能的原因："
            log_info "  1. 缺少编译工具（gcc/g++）"
            log_info "  2. 缺少 six 模块（protobuf 依赖）"
            log_info "  3. Python 开发头文件缺失"
        fi
        
        # 返回原目录
        cd - &> /dev/null || true
    else
        log_warning "⚠️  未找到 Protobuf Python 源码 ($protobuf_python_dir)"
        log_info "跳过 Protobuf Python 库安装"
    fi

    log_success "基础构建工具安装完成"
    log_info ""
    log_info "分布式编译配置:"
    log_info "  1. 主编译机: 创建 ci/distcc.conf 配置文件"
    log_info "  2. 远程编译机: 运行 sudo ./ci/setup-distccd.sh"
    log_info "  3. 详细说明: docs/分布式编译指南.md"
}

# 检查编译器（诊断用，主流程不再调用）
# 现在只在 init 模式完成时用于显示工具版本
check_compiler_for_diagnostics() {
    # 显示编译器信息
    local actual_gcc="${CC:-$(which gcc 2>/dev/null)}"
    local actual_gxx="${CXX:-$(which g++ 2>/dev/null)}"

    if [ -n "$actual_gcc" ] && [ -x "$actual_gcc" ]; then
        local gcc_version=$($actual_gcc --version 2>/dev/null | head -1 || echo "未知版本")
        log_info "gcc: ${actual_gcc}"
        log_info "  ${gcc_version}"
    fi

    if [ -n "$actual_gxx" ] && [ -x "$actual_gxx" ]; then
        local gxx_version=$($actual_gxx --version 2>/dev/null | head -1 || echo "未知版本")
        log_info "g++: ${actual_gxx}"
        log_info "  ${gxx_version}"
    fi
}

# 注意：ccache 配置已迁移到 CMake 系统（cmake/CompileCache.cmake）
# 此函数已删除，CMake 会自动处理 ccache 配置

# 准备构建环境
prepare_environment() {
    log_info "准备构建环境..."

    # 检查 Makefile
    if [ ! -f "Makefile" ]; then
        log_error "未找到 Makefile，请确保在项目根目录执行"
        exit 1
    fi

    # 检查必要的工具是否存在（不自动安装）
    local missing_tools=()
    
    if ! command -v gcc &> /dev/null; then
        missing_tools+=("gcc")
    fi
    
    if ! command -v g++ &> /dev/null; then
        missing_tools+=("g++")
    fi
    
    if ! command -v cmake &> /dev/null; then
        missing_tools+=("cmake")
    fi
    
    # 如果缺少关键工具，提示用户运行 init
    if [ ${#missing_tools[@]} -gt 0 ]; then
        log_error "缺少必要的构建工具: ${missing_tools[*]}"
        log_info ""
        log_info "解决方案："
        log_info "  1. 运行环境初始化: ./ci/build.sh init"
        log_info "  2. 或手动安装: sudo apt-get install build-essential cmake"
        log_info ""
        exit 1
    fi
    
    # 准备构建环境（复制 protoc 等）
    if [ ! -f ".build_env_setup" ]; then
        log_info "首次构建，准备 protoc..."
        
        # 只复制 protoc，不安装依赖
        local protoc_dir="tools/google3.6/src"
        if [ ! -f "$protoc_dir/protoc" ] && [ -f "tools/protoc" ]; then
            mkdir -p "$protoc_dir" 2>/dev/null || true
            cp "tools/protoc" "$protoc_dir/protoc" &> /dev/null || true
            chmod +x "$protoc_dir/protoc" &> /dev/null || true
            log_info "✅ protoc 已准备"
        fi
        
        touch .build_env_setup
    fi

    log_success "构建环境准备完成"
}

# 生成配置和代码
generate_code() {
    log_info "生成配置和代码..."

    # Windows 下 make 输出可能导致 stdout 缓冲区溢出，需要特殊处理
    local is_windows=false
    if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin" ]] || [[ -n "${WINDIR:-}" ]]; then
        is_windows=true
    fi

    if [ "$is_windows" = true ]; then
        # Windows 下：重定向输出到临时文件
        local temp_log="/tmp/make_auto_make_$(date +%Y%m%d_%H%M%S).log"
        if make auto-make GAME_DIR="${GAME_DIR}" > "$temp_log" 2>&1; then
            log_success "代码生成完成"
            rm -f "$temp_log" 2>/dev/null || true
        else
            log_error "代码生成失败"
            if [ -f "$temp_log" ] && [ -s "$temp_log" ]; then
                log_error "最后 50 行错误信息:"
                tail -50 "$temp_log" | while IFS= read -r line; do
                    log_error "  $line"
                done
            fi
            rm -f "$temp_log" 2>/dev/null || true
            exit 1
        fi
    else
        # Linux/macOS 下：正常执行
    make auto-make GAME_DIR="${GAME_DIR}" || {
        log_error "代码生成失败"
        exit 1
    }
    log_success "代码生成完成"
    fi
}

# 清理构建
# 注意: Makefile 的 build-*-all 目标已经包含了清理逻辑，所以这里不需要单独清理
clean_build() {
    # Makefile 的 build-*-all 和 build-*-patch-all 目标会自动清理
    # 这个函数保留为空，供将来扩展使用
    :
}

# 设置 distcc 监控（简化版）
# 注意：主机验证、JOBS 计算和动态均衡已迁移到 CMake 系统（cmake/DistccConfig.cmake）
# 此函数现在只提供监控提示，不执行复杂的监控逻辑
setup_distcc_monitor() {
    # 检查是否启用了 distcc（由 CMake 设置的环境变量）
    if [ -z "${DISTCC_HOSTS:-}" ]; then
        return 0
    fi

    # 检查 distccmon-text 是否可用
    if ! command -v distccmon-text &> /dev/null; then
        return 0
    fi

    # 只在终端中显示监控提示
    if [ -t 1 ]; then
        log_info ""
        log_info "💡 实时监控分布式编译:"
        log_info "  ${CYAN}distccmon-text${NC} 或 ${CYAN}watch -n 1 distccmon-text${NC}"
        log_info ""
        log_info "注意: 主机验证、JOBS 计算和动态均衡已由 CMake 自动处理"
        log_info ""
    fi
}

# 兼容旧代码：start_distcc_monitor 别名
start_distcc_monitor() {
    setup_distcc_monitor
}

# 停止 distcc 监控
stop_distcc_monitor() {
    # 停止监控进程
    if [ -n "$MONITOR_PID" ] && kill -0 "$MONITOR_PID" 2>/dev/null; then
        kill "$MONITOR_PID" 2>/dev/null || true
        wait "$MONITOR_PID" 2>/dev/null || true
        MONITOR_PID=""
    fi

    # 从 PID 文件读取并清理
    if [ -f "$MONITOR_PID_FILE" ]; then
        local pid=$(cat "$MONITOR_PID_FILE" 2>/dev/null)
        if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
            kill "$pid" 2>/dev/null || true
            wait "$pid" 2>/dev/null || true
        fi
        rm -f "$MONITOR_PID_FILE"
    fi

    # 不再清理临时文件，保留供后续使用
    # rm -f "$monitor_script" 2>/dev/null || true
}

# 简化的编译执行函数（统一使用标准输出）
build_with_split_screen() {
    local build_cmd="$1"
    
    # 检查是否启用了分布式编译，显示监控提示
    local distcc_enabled=false
    if [ -n "${DISTCC_HOSTS:-}" ] || [ -n "${CCACHE_PREFIX:-}" ]; then
        if [[ "${CCACHE_PREFIX:-}" == *"distcc"* ]] || [[ "${CCACHE_PREFIX:-}" == *"icecc"* ]]; then
            distcc_enabled=true
        fi
    fi
    
    if [ "$distcc_enabled" = "true" ] && command -v distccmon-text &> /dev/null; then
        log_info ""
        log_info "💡 查看分布式编译监控（在新终端运行）: ${CYAN}./ci/monitor-distcc.sh${NC}"
        log_info ""
    fi
    
    # 检测操作系统（Windows 下需要特殊处理 stdout 缓冲区问题）
    local is_windows=false
    if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin" ]] || [[ -n "${WINDIR:-}" ]]; then
        is_windows=true
    fi
    
    # Windows 下：直接重定向到文件，避免 stdout 缓冲区溢出
    # Linux/macOS 下：使用 tee 同时输出到终端和文件
    if [ "$is_windows" = true ]; then
        # Windows 下：先重定向到文件，然后显示最后几行
        if eval "$build_cmd" >> "$BUILD_LOG_FILE" 2>&1; then
            # 成功时显示最后 20 行
            if [ -f "$BUILD_LOG_FILE" ] && [ -s "$BUILD_LOG_FILE" ]; then
                tail -20 "$BUILD_LOG_FILE" | while IFS= read -r line; do
                    echo "$line"
                done
            fi
            return 0
        else
            # 失败时显示最后 50 行错误信息
            if [ -f "$BUILD_LOG_FILE" ] && [ -s "$BUILD_LOG_FILE" ]; then
                tail -50 "$BUILD_LOG_FILE" | while IFS= read -r line; do
                    echo "$line" >&2
                done
            fi
            return 1
        fi
    else
        # Linux/macOS 下：使用 tee 同时输出到终端和文件
        if command -v tee >/dev/null 2>&1; then
    eval "$build_cmd" 2>&1 | tee -a "$BUILD_LOG_FILE"
    return ${PIPESTATUS[0]}
        else
            # 如果没有 tee，只重定向到文件
            eval "$build_cmd" >> "$BUILD_LOG_FILE" 2>&1
            return $?
        fi
    fi
}

# 包装编译命令，添加监控信息
wrap_build_with_monitor() {
    local build_cmd="$1"
    
    # 创建构建日志文件
    export BUILD_LOG_FILE="/tmp/build_${BUILD_TYPE}_$(date +%Y%m%d_%H%M%S).log"
    log_info "📝 构建日志将保存到: ${BUILD_LOG_FILE}"

    # 检查是否启用了 distcc（支持 wrapper 模式）
    local distcc_enabled=false
    if [ -n "${DISTCC_HOSTS:-}" ] || [ -n "${DISTCC_HOSTS_ORIGINAL:-}" ] || [ -n "${DISTCC_HOSTS_FILE:-}" ]; then
        if [[ "${CCACHE_PREFIX:-}" == *"distcc"* ]] || [ -n "${DISTCC_WRAPPER:-}" ]; then
            distcc_enabled=true
        fi
    fi
    
    # 统一使用标准输出模式
    build_with_split_screen "$build_cmd"
    return $?
}

# 检查 CMake 缓存中的编译器路径是否有问题
check_cmake_compiler_path() {
    local cmake_cache_file="$1"
    if [ ! -f "$cmake_cache_file" ]; then
        return 0  # 文件不存在，无需检查
    fi
    
    # 检查 C 和 CXX 编译器路径是否指向 ccache 包装器
    local c_compiler=$(grep "^CMAKE_C_COMPILER:" "$cmake_cache_file" 2>/dev/null | cut -d'=' -f2 | tr -d '\n' || echo "")
    local cxx_compiler=$(grep "^CMAKE_CXX_COMPILER:" "$cmake_cache_file" 2>/dev/null | cut -d'=' -f2 | tr -d '\n' || echo "")
    
    # 检查是否指向 ccache 包装器（可能导致 distcc 递归调用）
    if [[ "$c_compiler" == *"/ccache/"* ]] || [[ "$cxx_compiler" == *"/ccache/"* ]]; then
        log_warning "检测到 CMake 缓存中的编译器路径指向 ccache 包装器"
        log_warning "  C 编译器: ${c_compiler:-未设置}"
        log_warning "  CXX 编译器: ${cxx_compiler:-未设置}"
        log_warning "这可能导致 distcc 递归调用问题，需要清理缓存"
        return 1  # 检测到问题
    fi
    
    return 0  # 路径正常
}

# 清理 CMake 缓存（仅在必要时，避免每次都重新配置）
clean_cmake_cache_if_distcc() {
    # 📝 新策略：在以下情况清理 CMake 缓存
    # 1. 用户设置了 FORCE_CMAKE_RECONFIGURE=1 环境变量
    # 2. 执行 *-all 目标（全量构建）
    # 3. 执行 clean-all 命令
    # 4. 检测到 CMake 缓存中的编译器路径指向 ccache 包装器（自动修复）
    # 
    # 不再每次使用 distcc 都清理缓存，因为：
    # - Makefile 已经实现了智能判断（检查 CMakeCache.txt 是否存在）
    # - 每次清理会导致失去增量编译的优势
    # - CMake 本身可以检测到 launcher 变化并自动重新配置
    
    # 如果是 *-all 目标或 clean-all 命令，清理所有缓存
    if [[ "${BUILD_TYPE}" == *-all ]] || [ "${BUILD_TYPE}" = "all-clean" ] || [ "${BUILD_TYPE}" = "clean-all" ]; then
        log_info "检测到全量构建目标或清理命令 (${BUILD_TYPE})，清理 CMake 缓存..."
        local cleaned_count=0
        for dir in Build/build64_*; do
            if [ -d "$dir" ] && [ -f "$dir/CMakeCache.txt" ]; then
                log_info "  清理: $dir"
                rm -rf "$dir/CMakeFiles" 2>/dev/null || true
                rm -f "$dir/CMakeCache.txt" 2>/dev/null || true
                cleaned_count=$((cleaned_count + 1))
            fi
        done
        if [ $cleaned_count -gt 0 ]; then
            log_success "CMake 缓存已清理（清理了 $cleaned_count 个构建目录）"
        else
            log_info "没有找到需要清理的 CMake 缓存"
        fi
        return 0
    fi
    
    # 确定当前构建目录
    local cmake_build_dir=""
    case "${BUILD_TYPE}" in
        debug|debug-patch)
            cmake_build_dir="Build/build64_debug"
            ;;
        release|release-patch)
            cmake_build_dir="Build/build64_release"
            ;;
        dynamic-debug|dynamic-debug-patch)
            cmake_build_dir="Build/build64_dynamic_debug"
            ;;
        dynamic-release|dynamic-release-patch)
            cmake_build_dir="Build/build64_dynamic_release"
            ;;
    esac
    
    # 如果用户强制要求重新配置
    if [ "${FORCE_CMAKE_RECONFIGURE:-0}" = "1" ]; then
        if [ -n "$cmake_build_dir" ] && [ -f "$cmake_build_dir/CMakeCache.txt" ]; then
            log_info "强制重新配置 CMake (FORCE_CMAKE_RECONFIGURE=1)..."
            rm -rf "$cmake_build_dir/CMakeFiles" 2>/dev/null || true
            rm -f "$cmake_build_dir/CMakeCache.txt" 2>/dev/null || true
            log_success "CMake 缓存已清理: $cmake_build_dir"
        fi
        return 0
    fi
    
    # 🔥 关键：自动检测并修复编译器路径问题（防止 distcc 递归调用）
    if [ -n "$cmake_build_dir" ] && [ -f "$cmake_build_dir/CMakeCache.txt" ]; then
        if ! check_cmake_compiler_path "$cmake_build_dir/CMakeCache.txt"; then
            log_warning "自动清理有问题的 CMake 缓存: $cmake_build_dir"
            rm -rf "$cmake_build_dir/CMakeFiles" 2>/dev/null || true
            rm -f "$cmake_build_dir/CMakeCache.txt" 2>/dev/null || true
            log_success "已清理 CMake 缓存，将重新配置（使用正确的编译器路径）"
            return 0
        fi
    fi
    
    # 💡 提示：如果需要强制重新配置 CMake，可以：
    # - 使用 *-all 目标：./ci/build.sh dynamic-debug-all
    # - 或设置环境变量：FORCE_CMAKE_RECONFIGURE=1 ./ci/build.sh dynamic-debug
}

# 执行构建
do_build() {
    # 显示构建模式和对应的 Makefile 目标
    log_info "开始构建 (${BUILD_TYPE})..."
    log_info "调用 Makefile 目标: make ${BUILD_TYPE}"

    # 构建参数
    BUILD_ARGS="GAME_DIR=${GAME_DIR} JOBS=${JOBS}"

    # 详细输出（可选）
    if [ "${VERBOSE}" = "true" ]; then
        BUILD_ARGS="${BUILD_ARGS} VERBOSE=1"
    fi
    
    # DRY_RUN 模式（仅打印命令，不执行）
    if [ "${DRY_RUN}" = "true" ]; then
        BUILD_ARGS="${BUILD_ARGS} DRY_RUN=1"
    fi
    
    # SKIP_MAKEFILES 模式（跳过代码生成）
    if [ "${SKIP_MAKEFILES}" = "1" ]; then
        BUILD_ARGS="${BUILD_ARGS} SKIP_MAKEFILES=1"
    fi
    
    # 传递 Clang 编译器选项（如果启用）
    if [ "${USE_CLANG:-0}" = "1" ]; then
        BUILD_ARGS="${BUILD_ARGS} USE_CLANG=1"
        if [ -n "${CLANG_VERSION:-}" ]; then
            BUILD_ARGS="${BUILD_ARGS} CLANG_VERSION=${CLANG_VERSION}"
        fi
        log_info "🔧 使用 Clang 编译器 (版本: ${CLANG_VERSION:-14}) ⚡"
    else
        log_info "🔧 使用 GCC 编译器"
    fi

    # 直接调用对应的 Makefile 目标
    case ${BUILD_TYPE} in
        auto-make|auto-make-all|auto-make-patch|auto-make-patch-all)
            # 代码生成不需要 distcc 监控，直接执行
            # Windows 下需要特殊处理 stdout 缓冲区问题
            local is_windows=false
            if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin" ]] || [[ -n "${WINDIR:-}" ]]; then
                is_windows=true
            fi

            if [ "$is_windows" = true ]; then
                # Windows 下：重定向输出到临时文件
                local temp_log="/tmp/make_${BUILD_TYPE}_$(date +%Y%m%d_%H%M%S).log"
                if make ${BUILD_TYPE} ${BUILD_ARGS} > "$temp_log" 2>&1; then
                    log_success "代码生成完成"
                    log_info "已完成 proto 和 Excel 文件的转换"
                    rm -f "$temp_log" 2>/dev/null || true
                else
                    log_error "代码生成失败: make ${BUILD_TYPE}"
                    if [ -f "$temp_log" ] && [ -s "$temp_log" ]; then
                        log_error "最后 50 行错误信息:"
                        tail -50 "$temp_log" | while IFS= read -r line; do
                            log_error "  $line"
                        done
                    fi
                    rm -f "$temp_log" 2>/dev/null || true
                    exit 1
                fi
            else
                # Linux/macOS 下：正常执行
            make ${BUILD_TYPE} ${BUILD_ARGS} || {
                log_error "代码生成失败: make ${BUILD_TYPE}"
                exit 1
            }
            log_success "代码生成完成"
            log_info "已完成 proto 和 Excel 文件的转换"
            fi
            ;;

        debug|debug-patch|debug-all|debug-patch-all)
            # 编译任务：ccache 和 distcc 配置已由 CMake 自动处理
            log_info "准备编译环境..."
            # 注意：ccache 和 distcc 配置已移动到 CMake 系统（cmake/CompileCache.cmake）
            # 不再需要手动调用 setup_ccache 和 load_distcc_config

            # 🔥 关键：在 distcc 配置后重新设置 BUILD_ARGS（使用更新后的 JOBS）
            BUILD_ARGS="GAME_DIR=${GAME_DIR} JOBS=${JOBS}"
            if [ "${VERBOSE}" = "true" ]; then
                BUILD_ARGS="${BUILD_ARGS} VERBOSE=1"
            fi
            if [ "${DRY_RUN}" = "true" ]; then
                BUILD_ARGS="${BUILD_ARGS} DRY_RUN=1"
            fi
            if [ "${SKIP_MAKEFILES}" = "1" ]; then
                BUILD_ARGS="${BUILD_ARGS} SKIP_MAKEFILES=1"
            fi
            # 传递 Clang 编译器选项（如果启用）
            if [ "${USE_CLANG:-0}" = "1" ]; then
                BUILD_ARGS="${BUILD_ARGS} USE_CLANG=1"
                if [ -n "${CLANG_VERSION:-}" ]; then
                    BUILD_ARGS="${BUILD_ARGS} CLANG_VERSION=${CLANG_VERSION}"
                fi
                log_info "🔧 使用 Clang 编译器 (版本: ${CLANG_VERSION:-14}) ⚡"
            else
                log_info "🔧 使用 GCC 编译器"
            fi
            
            # 显式导出CMAKE相关环境变量给make的子进程
            if [ -n "${CMAKE_C_COMPILER_LAUNCHER:-}" ]; then
                export CMAKE_C_COMPILER_LAUNCHER
                export CMAKE_CXX_COMPILER_LAUNCHER
            fi
            if [ -n "${CMAKE_C_COMPILER:-}" ]; then
                export CMAKE_C_COMPILER
                export CMAKE_CXX_COMPILER
            fi

            # 启动 distcc 监控
            start_distcc_monitor
            wrap_build_with_monitor "make ${BUILD_TYPE} ${BUILD_ARGS}" || {
                log_error "构建失败: make ${BUILD_TYPE}"
                if [ -n "${BUILD_LOG_FILE:-}" ] && [ -f "$BUILD_LOG_FILE" ]; then
                    log_error "📋 完整构建日志: ${BUILD_LOG_FILE}"
                fi
                stop_distcc_monitor
                exit 1
            }
            log_success "Debug 构建完成"
            log_info "构建产物: Install/Bin/Debug/"
            ls -lh Install/Bin/Debug/ 2>/dev/null | head -20 || log_warning "构建产物目录不存在"
            if [ -n "${BUILD_LOG_FILE:-}" ] && [ -f "$BUILD_LOG_FILE" ]; then
                log_success "📋 完整构建日志: ${BUILD_LOG_FILE}"
            fi
            ;;

        release|release-patch|release-all|release-patch-all)
            # 编译任务：ccache 和 distcc 配置已由 CMake 自动处理
            log_info "准备编译环境..."
            # 注意：ccache 和 distcc 配置已移动到 CMake 系统（cmake/CompileCache.cmake）
            # 不再需要手动调用 setup_ccache 和 load_distcc_config

            # 🔥 关键：在 distcc 配置后重新设置 BUILD_ARGS（使用更新后的 JOBS）
            BUILD_ARGS="GAME_DIR=${GAME_DIR} JOBS=${JOBS}"
            if [ "${VERBOSE}" = "true" ]; then
                BUILD_ARGS="${BUILD_ARGS} VERBOSE=1"
            fi
            if [ "${DRY_RUN}" = "true" ]; then
                BUILD_ARGS="${BUILD_ARGS} DRY_RUN=1"
            fi
            if [ "${SKIP_MAKEFILES}" = "1" ]; then
                BUILD_ARGS="${BUILD_ARGS} SKIP_MAKEFILES=1"
            fi
            # 传递 Clang 编译器选项（如果启用）
            if [ "${USE_CLANG:-0}" = "1" ]; then
                BUILD_ARGS="${BUILD_ARGS} USE_CLANG=1"
                if [ -n "${CLANG_VERSION:-}" ]; then
                    BUILD_ARGS="${BUILD_ARGS} CLANG_VERSION=${CLANG_VERSION}"
                fi
                log_info "🔧 使用 Clang 编译器 (版本: ${CLANG_VERSION:-14}) ⚡"
            else
                log_info "🔧 使用 GCC 编译器"
            fi
            log_info "📝 构建参数: ${BUILD_ARGS}"

            # 显式导出CMAKE相关环境变量给make的子进程
            if [ -n "${CMAKE_C_COMPILER_LAUNCHER:-}" ]; then
                export CMAKE_C_COMPILER_LAUNCHER
                export CMAKE_CXX_COMPILER_LAUNCHER
            fi
            if [ -n "${CMAKE_C_COMPILER:-}" ]; then
                export CMAKE_C_COMPILER
                export CMAKE_CXX_COMPILER
            fi

            # 启动 distcc 监控
            start_distcc_monitor
            wrap_build_with_monitor "make ${BUILD_TYPE} ${BUILD_ARGS}" || {
                log_error "构建失败: make ${BUILD_TYPE}"
                if [ -n "${BUILD_LOG_FILE:-}" ] && [ -f "$BUILD_LOG_FILE" ]; then
                    log_error "📋 完整构建日志: ${BUILD_LOG_FILE}"
                fi
                stop_distcc_monitor
                exit 1
            }

            # Strip 调试符号
            log_info "移除调试符号..."
            find Install/Bin/Release/ -type f -executable -exec strip --strip-unneeded {} \; 2>/dev/null || true

            log_success "Release 构建完成"
            log_info "构建产物: Install/Bin/Release/"
            ls -lh Install/Bin/Release/ 2>/dev/null | head -20 || log_warning "构建产物目录不存在"
            if [ -n "${BUILD_LOG_FILE:-}" ] && [ -f "$BUILD_LOG_FILE" ]; then
                log_success "📋 完整构建日志: ${BUILD_LOG_FILE}"
            fi
            ;;

        dynamic-debug|dynamic-debug-patch|dynamic-debug-all|dynamic-debug-patch-all)
            # 编译任务：加载分布式编译配置和 ccache
            log_info "准备编译环境..."
            # 注意：ccache 和 distcc 配置已移动到 CMake 系统（cmake/CompileCache.cmake）
            # 不再需要手动调用 setup_ccache 和 load_distcc_config

            # 🔥 关键：在 distcc 配置后重新设置 BUILD_ARGS（使用更新后的 JOBS）
            BUILD_ARGS="GAME_DIR=${GAME_DIR} JOBS=${JOBS}"
            if [ "${VERBOSE}" = "true" ]; then
                BUILD_ARGS="${BUILD_ARGS} VERBOSE=1"
            fi
            if [ "${DRY_RUN}" = "true" ]; then
                BUILD_ARGS="${BUILD_ARGS} DRY_RUN=1"
            fi
            if [ "${SKIP_MAKEFILES}" = "1" ]; then
                BUILD_ARGS="${BUILD_ARGS} SKIP_MAKEFILES=1"
            fi
            # 传递 Clang 编译器选项（如果启用）
            if [ "${USE_CLANG:-0}" = "1" ]; then
                BUILD_ARGS="${BUILD_ARGS} USE_CLANG=1"
                if [ -n "${CLANG_VERSION:-}" ]; then
                    BUILD_ARGS="${BUILD_ARGS} CLANG_VERSION=${CLANG_VERSION}"
                fi
                log_info "🔧 使用 Clang 编译器 (版本: ${CLANG_VERSION:-14}) ⚡"
            else
                BUILD_ARGS="${BUILD_ARGS} USE_CLANG=0"
                log_info "🔧 使用 GCC 编译器"
            fi
            
            # 🔥 关键：将真实编译器路径传递给 Makefile（作为 Makefile 变量）
            # Windows 上不传递编译器路径，让 CMake 自动检测 MSVC
            # Makefile 使用 $(CMAKE_C_COMPILER) 变量，优先使用显式传入的路径
            # 检测 Windows 系统（支持多种方式）
            local is_windows=false
            if [ -n "${WINDIR:-}" ] || [ -n "${SystemRoot:-}" ]; then
                is_windows=true
            elif [ -n "${OS:-}" ] && [[ "${OS:-}" == *"Windows"* ]]; then
                is_windows=true
            elif command -v uname >/dev/null 2>&1 && [ "$(uname -s 2>/dev/null | grep -iE 'MINGW|MSYS|CYGWIN')" ]; then
                is_windows=true
            fi
            
            if [ "$is_windows" = "false" ]; then
                # 仅在 Linux/macOS 上传递编译器路径
                if [ -n "${CMAKE_C_COMPILER:-}" ]; then
                    BUILD_ARGS="${BUILD_ARGS} CMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
                    log_info "✅ 传递 C 编译器路径给 Makefile: ${CMAKE_C_COMPILER}"
                fi
                if [ -n "${CMAKE_CXX_COMPILER:-}" ]; then
                    BUILD_ARGS="${BUILD_ARGS} CMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
                    log_info "✅ 传递 CXX 编译器路径给 Makefile: ${CMAKE_CXX_COMPILER}"
                fi
            else
                log_info "✅ Windows 系统：不传递编译器路径，让 CMake 自动检测 MSVC"
            fi
            
            # 显式导出CMAKE launcher环境变量给make的子进程
            if [ -n "${CMAKE_C_COMPILER_LAUNCHER:-}" ]; then
                export CMAKE_C_COMPILER_LAUNCHER
                export CMAKE_CXX_COMPILER_LAUNCHER
                BUILD_ARGS="${BUILD_ARGS} CMAKE_C_COMPILER_LAUNCHER=${CMAKE_C_COMPILER_LAUNCHER}"
                BUILD_ARGS="${BUILD_ARGS} CMAKE_CXX_COMPILER_LAUNCHER=${CMAKE_CXX_COMPILER_LAUNCHER}"
                log_info "✅ 传递 CMAKE launcher 给 Makefile: ${CMAKE_C_COMPILER_LAUNCHER}"
            fi
            
            log_info "📝 构建参数: ${BUILD_ARGS}"

            # 启动 distcc 监控
            start_distcc_monitor
            wrap_build_with_monitor "make ${BUILD_TYPE} ${BUILD_ARGS}" || {
                log_error "构建失败: make ${BUILD_TYPE}"
                if [ -n "${BUILD_LOG_FILE:-}" ] && [ -f "$BUILD_LOG_FILE" ]; then
                    log_error "📋 完整构建日志: ${BUILD_LOG_FILE}"
                fi
                stop_distcc_monitor
                exit 1
            }
            log_success "Dynamic Debug 构建完成"
            log_info "构建产物: Install/Bin/DynamicDebug/"
            ls -lh Install/Bin/DynamicDebug/ 2>/dev/null | head -20 || log_warning "构建产物目录不存在"
            if [ -n "${BUILD_LOG_FILE:-}" ] && [ -f "$BUILD_LOG_FILE" ]; then
                log_success "📋 完整构建日志: ${BUILD_LOG_FILE}"
            fi
            ;;

        dynamic-release|dynamic-release-patch|dynamic-release-all|dynamic-release-patch-all)
            # 编译任务：加载分布式编译配置和 ccache
            log_info "准备编译环境..."
            # 注意：ccache 和 distcc 配置已移动到 CMake 系统（cmake/CompileCache.cmake）
            # 不再需要手动调用 setup_ccache 和 load_distcc_config

            # 🔥 关键：在 distcc 配置后重新设置 BUILD_ARGS（使用更新后的 JOBS）
            BUILD_ARGS="GAME_DIR=${GAME_DIR} JOBS=${JOBS}"
            if [ "${VERBOSE}" = "true" ]; then
                BUILD_ARGS="${BUILD_ARGS} VERBOSE=1"
            fi
            if [ "${DRY_RUN}" = "true" ]; then
                BUILD_ARGS="${BUILD_ARGS} DRY_RUN=1"
            fi
            if [ "${SKIP_MAKEFILES}" = "1" ]; then
                BUILD_ARGS="${BUILD_ARGS} SKIP_MAKEFILES=1"
            fi
            # 传递 Clang 编译器选项（如果启用）
            if [ "${USE_CLANG:-0}" = "1" ]; then
                BUILD_ARGS="${BUILD_ARGS} USE_CLANG=1"
                if [ -n "${CLANG_VERSION:-}" ]; then
                    BUILD_ARGS="${BUILD_ARGS} CLANG_VERSION=${CLANG_VERSION}"
                fi
                log_info "🔧 使用 Clang 编译器 (版本: ${CLANG_VERSION:-14}) ⚡"
            else
                log_info "🔧 使用 GCC 编译器"
            fi
            log_info "📝 构建参数: ${BUILD_ARGS}"

            # 显式导出CMAKE相关环境变量给make的子进程
            if [ -n "${CMAKE_C_COMPILER_LAUNCHER:-}" ]; then
                export CMAKE_C_COMPILER_LAUNCHER
                export CMAKE_CXX_COMPILER_LAUNCHER
            fi
            if [ -n "${CMAKE_C_COMPILER:-}" ]; then
                export CMAKE_C_COMPILER
                export CMAKE_CXX_COMPILER
            fi

            # 启动 distcc 监控
            start_distcc_monitor
            wrap_build_with_monitor "make ${BUILD_TYPE} ${BUILD_ARGS}" || {
                log_error "构建失败: make ${BUILD_TYPE}"
                if [ -n "${BUILD_LOG_FILE:-}" ] && [ -f "$BUILD_LOG_FILE" ]; then
                    log_error "📋 完整构建日志: ${BUILD_LOG_FILE}"
                fi
                stop_distcc_monitor
                exit 1
            }

            # Strip 调试符号
            log_info "移除调试符号..."
            find Install/Bin/DynamicRelease/ -type f -executable -exec strip --strip-unneeded {} \; 2>/dev/null || true
            find Install/Bin/DynamicRelease/ -type f -name "*.so" -exec strip --strip-unneeded {} \; 2>/dev/null || true

            log_success "Dynamic Release 构建完成"
            log_info "构建产物: Install/Bin/DynamicRelease/"
            ls -lh Install/Bin/DynamicRelease/ 2>/dev/null | head -20 || log_warning "构建产物目录不存在"
            if [ -n "${BUILD_LOG_FILE:-}" ] && [ -f "$BUILD_LOG_FILE" ]; then
                log_success "📋 完整构建日志: ${BUILD_LOG_FILE}"
            fi
            ;;

        clean-all)
            # 清理所有构建目录的 CMake 缓存
            log_info "=========================================="
            log_info "清理所有构建目录的 CMake 缓存"
            log_info "=========================================="
            clean_cmake_cache_if_distcc
            log_success "清理完成"
            log_info ""
            log_info "已清理的构建目录："
            log_info "  - Build/build64_debug"
            log_info "  - Build/build64_release"
            log_info "  - Build/build64_dynamic_debug"
            log_info "  - Build/build64_dynamic_release"
            log_info ""
            log_info "💡 提示：现在可以重新运行构建命令"
            log_info "   例如: ./ci/build.sh dynamic-debug"
            return 0
            ;;

        all|all-clean)
            # 构建所有版本 - 根据是否清理选择不同的目标
            # 编译任务：加载分布式编译配置和 ccache
            log_info "准备编译环境..."
            # 注意：ccache 和 distcc 配置已移动到 CMake 系统（cmake/CompileCache.cmake）
            # 不再需要手动调用 setup_ccache 和 load_distcc_config

            # 🔥 关键：在 distcc 配置后重新设置 BUILD_ARGS（使用更新后的 JOBS）
            BUILD_ARGS="GAME_DIR=${GAME_DIR} JOBS=${JOBS}"
            if [ "${VERBOSE}" = "true" ]; then
                BUILD_ARGS="${BUILD_ARGS} VERBOSE=1"
            fi
            if [ "${DRY_RUN}" = "true" ]; then
                BUILD_ARGS="${BUILD_ARGS} DRY_RUN=1"
            fi
            if [ "${SKIP_MAKEFILES}" = "1" ]; then
                BUILD_ARGS="${BUILD_ARGS} SKIP_MAKEFILES=1"
            fi
            # 传递 Clang 编译器选项（如果启用）
            if [ "${USE_CLANG:-0}" = "1" ]; then
                BUILD_ARGS="${BUILD_ARGS} USE_CLANG=1"
                if [ -n "${CLANG_VERSION:-}" ]; then
                    BUILD_ARGS="${BUILD_ARGS} CLANG_VERSION=${CLANG_VERSION}"
                fi
                log_info "🔧 使用 Clang 编译器 (版本: ${CLANG_VERSION:-14}) ⚡"
            else
                log_info "🔧 使用 GCC 编译器"
            fi
            log_info "📝 构建参数: ${BUILD_ARGS}"

            # 启动 distcc 监控
            start_distcc_monitor

            # Windows 下需要特殊处理 stdout 缓冲区问题
            local is_windows=false
            if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]] || [[ "$OSTYPE" == "cygwin" ]] || [[ -n "${WINDIR:-}" ]]; then
                is_windows=true
            fi

            if [ "${CLEAN_BUILD}" = "true" ]; then
                log_info "构建所有版本（清理后）..."

                log_info "1/4 构建 Debug 版本（清理后）..."
                if [ "$is_windows" = true ]; then
                    make debug-all ${BUILD_ARGS} > "/tmp/make_debug_all.log" 2>&1 || log_warning "Debug 构建失败"
                else
                make debug-all ${BUILD_ARGS} || log_warning "Debug 构建失败"
                fi

                log_info "2/4 构建 Dynamic Debug 版本（清理后）..."
                if [ "$is_windows" = true ]; then
                    make dynamic-debug-all ${BUILD_ARGS} > "/tmp/make_dynamic_debug_all.log" 2>&1 || log_warning "Dynamic Debug 构建失败"
                else
                make dynamic-debug-all ${BUILD_ARGS} || log_warning "Dynamic Debug 构建失败"
                fi

                log_info "3/4 构建 Release 版本（清理后）..."
                if [ "$is_windows" = true ]; then
                    make release-all ${BUILD_ARGS} > "/tmp/make_release_all.log" 2>&1 || log_warning "Release 构建失败"
                else
                make release-all ${BUILD_ARGS} || log_warning "Release 构建失败"
                fi

                log_info "4/4 构建 Dynamic Release 版本（清理后）..."
                if [ "$is_windows" = true ]; then
                    make dynamic-release-all ${BUILD_ARGS} > "/tmp/make_dynamic_release_all.log" 2>&1 || log_warning "Dynamic Release 构建失败"
                else
                make dynamic-release-all ${BUILD_ARGS} || log_warning "Dynamic Release 构建失败"
                fi
            else
                log_info "构建所有版本（标准）..."

                log_info "1/4 构建 Debug 版本..."
                if [ "$is_windows" = true ]; then
                    make debug ${BUILD_ARGS} > "/tmp/make_debug.log" 2>&1 || log_warning "Debug 构建失败"
                else
                make debug ${BUILD_ARGS} || log_warning "Debug 构建失败"
                fi

                log_info "2/4 构建 Dynamic Debug 版本..."
                if [ "$is_windows" = true ]; then
                    make dynamic-debug ${BUILD_ARGS} > "/tmp/make_dynamic_debug.log" 2>&1 || log_warning "Dynamic Debug 构建失败"
                else
                make dynamic-debug ${BUILD_ARGS} || log_warning "Dynamic Debug 构建失败"
                fi

                log_info "3/4 构建 Release 版本..."
                if [ "$is_windows" = true ]; then
                    make release ${BUILD_ARGS} > "/tmp/make_release.log" 2>&1 || log_warning "Release 构建失败"
                else
                make release ${BUILD_ARGS} || log_warning "Release 构建失败"
                fi

                log_info "4/4 构建 Dynamic Release 版本..."
                if [ "$is_windows" = true ]; then
                    make dynamic-release ${BUILD_ARGS} > "/tmp/make_dynamic_release.log" 2>&1 || log_warning "Dynamic Release 构建失败"
                else
                make dynamic-release ${BUILD_ARGS} || log_warning "Dynamic Release 构建失败"
                fi
            fi

            log_success "所有版本构建完成"
            log_info "构建产物:"
            ls -lh Install/Bin/*/ 2>/dev/null || log_warning "构建产物目录不存在"
            if [ -n "${BUILD_LOG_FILE:-}" ] && [ -f "$BUILD_LOG_FILE" ]; then
                log_success "📋 完整构建日志: ${BUILD_LOG_FILE}"
            fi
            ;;

        *)
            log_error "未知的构建类型: ${BUILD_TYPE}"
            log_info "支持的类型:"
            log_info "  代码生成:"
            log_info "    auto-make, auto-make-all, auto-make-patch, auto-make-patch-all"
            log_info "  标准构建:"
            log_info "    debug, release, dynamic-debug (默认), dynamic-release"
            log_info "  补丁构建（GAME_VERSION_PATCH=1）:"
            log_info "    debug-patch, release-patch, dynamic-debug-patch, dynamic-release-patch"
            log_info "  清理后标准构建:"
            log_info "    debug-all, release-all, dynamic-debug-all, dynamic-release-all"
            log_info "  清理后补丁构建:"
            log_info "    debug-patch-all, release-patch-all, dynamic-debug-patch-all, dynamic-release-patch-all"
            log_info "  特殊:"
            log_info "    all, all-clean, clean-all"
            stop_distcc_monitor
            exit 1
            ;;
    esac

    # 停止监控
    stop_distcc_monitor
}

# 显示构建统计
show_build_stats() {
    log_info "=========================================="
    log_info "构建统计"
    log_info "=========================================="

    # 计算构建时间
    BUILD_END_TIME=$(date +%s)
    BUILD_DURATION=$((BUILD_END_TIME - BUILD_START_TIME))
    BUILD_DURATION_MIN=$((BUILD_DURATION / 60))
    BUILD_DURATION_SEC=$((BUILD_DURATION % 60))

    log_info "构建时间: ${BUILD_DURATION_MIN} 分 ${BUILD_DURATION_SEC} 秒"

    # 显示 ccache 统计
    log_info ""
    log_info "ccache 统计:"
    
    # 注意：ccache 配置已迁移到 CMake，缓存目录在构建目录下
    # 尝试从构建目录获取缓存路径
    local ccache_dir=""
    local build_type_lower=$(echo "${BUILD_TYPE}" | tr '[:upper:]' '[:lower:]' | sed 's/-/_/g')
    
    # 尝试多种可能的构建目录名称
    for dir in "Build/build64_${build_type_lower}" "Build/build64_debug" "Build/build64_release" "Build/build64_dynamic_debug" "Build/build64_dynamic_release"; do
        if [ -f "$dir/ccache_launcher.sh" ]; then
            ccache_dir=$(grep "CCACHE_DIR=" "$dir/ccache_launcher.sh" | head -1 | cut -d'"' -f2)
            break
        elif [ -f "$dir/ccache_distcc_launcher.sh" ]; then
            ccache_dir=$(grep "CCACHE_DIR=" "$dir/ccache_distcc_launcher.sh" | head -1 | cut -d'"' -f2)
            break
        fi
    done
    
    if [ -n "$ccache_dir" ] && [ -d "$ccache_dir" ]; then
        log_info "  缓存目录: $ccache_dir"
        CCACHE_DIR="$ccache_dir" ccache -s
    else
        log_info "  缓存目录: 未检测到（使用默认）"
        ccache -s
    fi
    
    log_info "=========================================="
    log_success "构建完成！"
    log_info "=========================================="
}

# 生成构建报告
generate_build_report() {
    local REPORT_FILE="build-report.txt"
    
    log_info "生成构建报告: ${REPORT_FILE}"
    
    cat > "${REPORT_FILE}" <<EOF
NFShmXFrame 构建报告
========================================

构建信息:
  项目: ${GAME_DIR}
  构建类型: ${BUILD_TYPE}
  构建时间: $(date)
  构建时长: ${BUILD_DURATION_MIN} 分 ${BUILD_DURATION_SEC} 秒
  并行任务数: ${JOBS}
  清理构建: ${CLEAN_BUILD}

系统信息:
  操作系统: ${OS} ${VER}
  主机名: $(hostname)
  CPU核心数: $(nproc)
  内存: $(free -h | grep Mem | awk '{print $2}')

Git 信息:
  提交哈希: $(git rev-parse HEAD 2>/dev/null || echo "N/A")
  分支: $(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "N/A")
  作者: $(git log -1 --pretty=format:'%an <%ae>' 2>/dev/null || echo "N/A")
  提交信息: $(git log -1 --pretty=format:'%s' 2>/dev/null || echo "N/A")

ccache 统计:
$(
# 尝试从构建目录获取缓存路径
ccache_dir=""
for dir in Build/build64_*/ccache_launcher.sh Build/build64_*/ccache_distcc_launcher.sh; do
    if [ -f "$dir" ]; then
        ccache_dir=$(grep "CCACHE_DIR=" "$dir" | head -1 | cut -d'"' -f2)
        break
    fi
done

if [ -n "$ccache_dir" ] && [ -d "$ccache_dir" ]; then
    CCACHE_DIR="$ccache_dir" ccache -s
else
    ccache -s
fi
)

构建产物:
$(ls -lh Install/Bin/*/ 2>/dev/null || echo "无")

========================================
EOF

    log_success "构建报告已生成: ${REPORT_FILE}"
}

# 主流程
main() {
    # 检测操作系统
    detect_os
    
    # 调试信息：显示关键变量（帮助诊断 sudo 请求问题）
    if [ "${VERBOSE}" = "true" ] || [ "${DEBUG_MODE}" = "true" ]; then
        log_info "========================================"
        log_info "调试信息："
        log_info "  INIT_MODE = ${INIT_MODE}"
        log_info "  SKIP_INSTALL_DEPS = ${SKIP_INSTALL_DEPS}"
        log_info "  BUILD_TYPE = ${BUILD_TYPE}"
        log_info "========================================"
    fi
    
    # 强制检查：如果不是 init 模式，确保跳过依赖安装
    if [ "$INIT_MODE" != true ]; then
        # 检测异常的环境变量设置
        if [ "${SKIP_INSTALL_DEPS}" = "0" ]; then
            log_warning "========================================"
            log_warning "检测到异常配置"
            log_warning "========================================"
            log_warning "SKIP_INSTALL_DEPS=0，但当前不是 init 模式"
            log_warning "强制设置为 SKIP_INSTALL_DEPS=1（跳过依赖安装）"
            log_warning ""
            log_info "如需安装依赖，请运行: ./ci/build.sh init"
            log_warning "========================================"
            # 强制跳过依赖安装
            SKIP_INSTALL_DEPS=1
        fi
    fi
    
    # 安装依赖（仅 init 模式）
    # 强制检查：非 init 模式绝不安装依赖，即使环境变量设置了 SKIP_INSTALL_DEPS=0
    if [ "$INIT_MODE" = true ] && [ "${SKIP_INSTALL_DEPS}" != "1" ]; then
        # 提前请求 sudo 权限（避免中途需要输入密码）
        if [ "$EUID" -ne 0 ]; then
            log_info "检测到需要安装依赖，请输入 sudo 密码（仅需一次）..."
            sudo -v || {
                log_error "无法获取 sudo 权限"
                log_info "解决方案："
                log_info "  1. 跳过依赖安装: ./ci/build.sh（默认跳过）"
                log_info "  2. 手动安装依赖: ./install_dependencies.sh --root"
                log_info "  3. 配置 sudo 免密码: 见 docs/sudo免密码配置.md"
                exit 1
            }
            
            # 保持 sudo 会话活跃（后台更新时间戳）
            (
                while true; do
                    sudo -n true
                    sleep 50
                done
            ) 2>/dev/null &
            SUDO_KEEPER_PID=$!
        fi
        
        case ${OS} in
            *Ubuntu*|*Debian*)
                if ! install_deps_ubuntu; then
                    log_error "依赖安装失败，无法继续"
                    exit 1
                fi
                ;;
            *CentOS*|*Red\ Hat*)
                if ! install_deps_centos; then
                    log_error "依赖安装失败，无法继续"
                    exit 1
                fi
                ;;
            *)
                log_warning "未知的操作系统: ${OS}"
                log_info "请手动安装以下工具："
                log_info "  - gcc, g++, make"
                log_info "  - cmake (>= 3.10)"
                log_info "  - ninja-build (推荐)"
                log_info "  - ccache (推荐)"
                log_info "  - python2.7 或 python3"
                log_warning "跳过依赖安装，继续执行..."
                ;;
        esac
        
        # 清理 sudo keeper 进程
        if [ -n "${SUDO_KEEPER_PID:-}" ]; then
            kill $SUDO_KEEPER_PID 2>/dev/null || true
        fi
        
        # 如果是初始化模式，完成后退出
        if [ "$INIT_MODE" = true ]; then
            log_success "=========================================="
            log_success "环境初始化完成！"
            log_info ""
            log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
            log_info "📦 已安装组件:"
            
            # 辅助函数：自动安装工具
            auto_install_tool() {
                local tool_name=$1
                local ubuntu_pkg=$2
                local centos_pkg=$3
                local check_cmd=$4
                
                if command -v "$check_cmd" &> /dev/null; then
                    return 0  # 已安装
                fi
                
                log_warning "  ⚠️  $tool_name: 未安装"
                log_info "正在自动安装 $tool_name..."
                
                local install_sudo=""
                if [ "$EUID" -ne 0 ]; then
                    install_sudo="sudo"
                fi
                
                case ${OS} in
                    *Ubuntu*|*Debian*)
                        if [ -n "$ubuntu_pkg" ]; then
                            if $install_sudo apt-get install -y -qq $ubuntu_pkg 2>/dev/null; then
                                if command -v "$check_cmd" &> /dev/null; then
                                    log_success "  ✅ $tool_name 安装成功"
                                    return 0
                                fi
                            fi
                        fi
                        log_warning "  ⚠️  $tool_name 自动安装失败，请手动安装: sudo apt-get install -y $ubuntu_pkg"
                        ;;
                    *CentOS*|*Red\ Hat*)
                        if [ -n "$centos_pkg" ]; then
                            if $install_sudo yum install -y -q $centos_pkg 2>/dev/null; then
                                if command -v "$check_cmd" &> /dev/null; then
                                    log_success "  ✅ $tool_name 安装成功"
                                    return 0
                                fi
                            fi
                        fi
                        log_warning "  ⚠️  $tool_name 自动安装失败，请手动安装: sudo yum install -y $centos_pkg"
                        ;;
                    *)
                        log_info "  ⚠️  请根据您的操作系统手动安装 $tool_name"
                        ;;
                esac
                return 1
            }
            
            # 显示编译工具链版本
            if command -v gcc &> /dev/null; then
                log_info "  ✅ gcc: $(gcc --version 2>&1 | head -n1 | sed 's/^gcc (.*) //')"
            else
                auto_install_tool "gcc" "gcc" "gcc" "gcc"
                if command -v gcc &> /dev/null; then
                    log_info "  ✅ gcc: $(gcc --version 2>&1 | head -n1 | sed 's/^gcc (.*) //')"
                fi
            fi
            
            if command -v g++ &> /dev/null; then
                log_info "  ✅ g++: $(g++ --version 2>&1 | head -n1 | sed 's/^g++ (.*) //')"
            else
                auto_install_tool "g++" "g++" "gcc-c++" "g++"
                if command -v g++ &> /dev/null; then
                    log_info "  ✅ g++: $(g++ --version 2>&1 | head -n1 | sed 's/^g++ (.*) //')"
                fi
            fi
            
            if command -v make &> /dev/null; then
                log_info "  ✅ make: $(make --version 2>&1 | head -n1)"
            else
                auto_install_tool "make" "make" "make" "make"
                if command -v make &> /dev/null; then
                    log_info "  ✅ make: $(make --version 2>&1 | head -n1)"
                fi
            fi
            
            # 显示构建工具版本
            if command -v cmake &> /dev/null; then
                log_info "  ✅ cmake: $(cmake --version 2>&1 | head -n1 | sed 's/cmake version //')"
            elif command -v cmake3 &> /dev/null; then
                log_info "  ✅ cmake3: $(cmake3 --version 2>&1 | head -n1 | sed 's/cmake version //')"
            else
                auto_install_tool "cmake" "cmake" "cmake3" "cmake"
                if command -v cmake &> /dev/null; then
                    log_info "  ✅ cmake: $(cmake --version 2>&1 | head -n1 | sed 's/cmake version //')"
                elif command -v cmake3 &> /dev/null; then
                    log_info "  ✅ cmake3: $(cmake3 --version 2>&1 | head -n1 | sed 's/cmake version //')"
                fi
            fi
            
            # 显示编译加速工具
            if command -v ccache &> /dev/null; then
                log_info "  ✅ ccache: $(ccache --version 2>&1 | head -n1)"
            else
                auto_install_tool "ccache" "ccache" "ccache" "ccache"
                if command -v ccache &> /dev/null; then
                    log_info "  ✅ ccache: $(ccache --version 2>&1 | head -n1)"
                fi
            fi
            
            # 显示分布式编译工具
            if command -v distcc &> /dev/null; then
                log_info "  ✅ distcc: $(distcc --version 2>&1 | head -n1)"
            else
                auto_install_tool "distcc" "distcc" "distcc" "distcc"
                if command -v distcc &> /dev/null; then
                    log_info "  ✅ distcc: $(distcc --version 2>&1 | head -n1)"
                fi
            fi
            
            # 显示 Python 环境
            if command -v python &> /dev/null; then
                log_info "  ✅ python: $(python --version 2>&1)"
            elif command -v python2 &> /dev/null; then
                log_info "  ✅ python2: $(python2 --version 2>&1)"
            elif command -v python3 &> /dev/null; then
                log_info "  ✅ python3: $(python3 --version 2>&1)"
            else
                log_warning "  ⚠️  python: 未安装"
                log_info "正在自动安装 python..."
                
                local install_sudo=""
                if [ "$EUID" -ne 0 ]; then
                    install_sudo="sudo"
                fi
                
                case ${OS} in
                    *Ubuntu*|*Debian*)
                        # 尝试安装 python2.7，如果失败则安装 python3
                        if $install_sudo apt-get install -y -qq python2.7 2>/dev/null && command -v python2.7 &> /dev/null; then
                            log_success "  ✅ python2.7 安装成功: $(python2.7 --version 2>&1)"
                        elif $install_sudo apt-get install -y -qq python3 2>/dev/null && command -v python3 &> /dev/null; then
                            log_success "  ✅ python3 安装成功: $(python3 --version 2>&1)"
                        else
                            log_warning "  ⚠️  python 自动安装失败，请手动安装: sudo apt-get install -y python2.7 或 python3"
                        fi
                        ;;
                    *CentOS*|*Red\ Hat*)
                        # 尝试安装 python2，如果失败则安装 python3
                        if $install_sudo yum install -y -q python2 2>/dev/null && command -v python2 &> /dev/null; then
                            log_success "  ✅ python2 安装成功: $(python2 --version 2>&1)"
                        elif $install_sudo yum install -y -q python3 2>/dev/null && command -v python3 &> /dev/null; then
                            log_success "  ✅ python3 安装成功: $(python3 --version 2>&1)"
                        else
                            log_warning "  ⚠️  python 自动安装失败，请手动安装: sudo yum install -y python2 或 python3"
                        fi
                        ;;
                    *)
                        log_info "  ⚠️  请根据您的操作系统手动安装 python"
                        ;;
                esac
                
                # 显示最终安装的 python 版本
                if command -v python &> /dev/null; then
                    log_info "  ✅ python: $(python --version 2>&1)"
                elif command -v python2 &> /dev/null; then
                    log_info "  ✅ python2: $(python2 --version 2>&1)"
                elif command -v python3 &> /dev/null; then
                    log_info "  ✅ python3: $(python3 --version 2>&1)"
                fi
            fi
            log_info ""
            log_info "🚀 快速开始:"
            log_info "  ./ci/build.sh dynamic-debug"
            log_info ""
            log_info "⚡ 启用分布式编译（可选）:"
            log_info "  主编译机: cp ci/distcc.conf.example ci/distcc.conf"
            log_info "           vim ci/distcc.conf  # 配置团队所有机器IP"
            log_info "  远程编译机: sudo ./ci/setup-distccd.sh"
            log_info ""
            log_info "📖 更多信息:"
            log_info "  - 构建指南: ci/README.md"
            log_info "  - 分布式编译: docs/分布式编译指南.md"
            log_info "  - 团队共享配置: docs/团队共享配置指南.md"
            log_info "  - 故障排查: docs/故障排查指南.md"
            log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
            log_info ""
            exit 0
        fi
    else
        if [ "$INIT_MODE" = true ]; then
            log_error "初始化模式下无法跳过依赖安装"
            log_info "请使用: ./ci/build.sh init（不要设置 SKIP_INSTALL_DEPS=1）"
            exit 1
        fi
        
        # 警告：如果在非 init 模式下设置了 SKIP_INSTALL_DEPS=0
        if [ "${SKIP_INSTALL_DEPS}" = "0" ]; then
            log_warning "⚠️  检测到 SKIP_INSTALL_DEPS=0，但当前不是 init 模式"
            log_info "非 init 模式下不会安装依赖（即使设置 SKIP_INSTALL_DEPS=0）"
            log_info "如需安装依赖，请运行: ./ci/build.sh init"
            log_info ""
        fi
        
        log_info "跳过依赖安装（默认行为）"
        log_info "提示: 首次使用请运行 './ci/build.sh init' 初始化环境"
    fi
    
    # 只在非 init 模式下进行快速的编译器检查（不安装）
    if [ "$INIT_MODE" != true ]; then
        # 快速检查编译器是否存在（不详细验证）
        if ! command -v gcc &> /dev/null || ! command -v g++ &> /dev/null; then
            log_error "编译器未安装（gcc/g++ 缺失）"
            log_info ""
            log_info "解决方案："
            log_info "  运行环境初始化: ./ci/build.sh init"
            log_info ""
            exit 1
        fi
        
        # 设置编译器环境变量
        export CC=${CC:-$(which gcc)}
        export CXX=${CXX:-$(which g++)}
    fi
    
    # 准备构建环境
    prepare_environment
    
    # 执行构建
    do_build
    
    # 显示构建统计
    show_build_stats
    
    # 生成构建报告
    generate_build_report
}

# 执行主流程
main "$@"

